How to adjust the drop down width of ComboBox?

5 10 2008


Combobox is good, because they utilize less space and at the same time they can show a list of options. But did you noticed one thing? By default the dropdown width of combobox is same as the width of combobox itself. If you add a loooong string to combobox, it will be displayed partially in the drop down list. So how to stretch the with of dropdown list of combobox?


If you are using MFC, you could use the api – CComboBox::SetDroppedWidth() or else you could use the message CB_SETDROPPEDWIDTH. First of all you’ve to iterate all strings in the combobox list and find out the required width. Then set the new drop down width of combobox. See the MFC code snippet for doing so. Code snippet is taken from MSDN and has been modified appropriately.

void CComboBoxDemoDlg::AdjustDropDownWidth()
{
    // Find the longest string in the combo box.
    CComboBox* pComboBox =
        ( CComboBox* ) GetDlgItem( IDC_CMB_STRINGS );
    int MaxWidth = 0;
    CDC* pDC = pComboBox->GetDC();

    // Iterate through all strings in Combobox and get MaxWidth
    CString String;
    CSize TextSize;
    for ( int Index = 0; Index < pComboBox->GetCount(); Index++ )
    {
        // Get n'th string.
        pComboBox->GetLBText( Index, String );

        // Get TextExtend
        TextSize = pDC->GetTextExtent( String );

        // Get MaxWidth.
        if( TextSize.cx > MaxWidth )
        {
            MaxWidth = TextSize.cx;
        }
    }

    pComboBox->ReleaseDC( pDC );

    // Adjust the width for the vertical scroll bar and
    // the left and right border.
    MaxWidth += ::GetSystemMetrics(SM_CXVSCROLL) +
                2 * ::GetSystemMetrics(SM_CXEDGE);

    // Set the dropdown width of combobox.
    pComboBox->SetDroppedWidth( MaxWidth );
}


You could achieve the same by sending CB_SETDROPPEDWIDTH by using SendMessage().


Targeted Audience – Intermediate.





How to find whether a GUI application is freezed or is not responding?

25 04 2008

It’s common that windows citizens usually hang after long run. 😉 Sometimes your application was meant to run for long period but stop responding after days or months. So how to automatically restart it if it gets hang? One method is to schedule a polling application which checks the application periodically. But how to determine whether an application is hung?


You can send WM_NULL message to the application window by using the api – SendMessageTimeout(). The WM_NULL does nothing. It can be used for poll the window. If an appliaction window is hung, it may not be able to process the WM_NULL message. If we use SendMessage(), since its a blocking call out caller thread too will be blocked.

So we should use SendMessageTimeout() in which we can specify a timeout. In SendMessageTimeout() we can specify a flag – SMTO_ABORTIFHUNG which returns immedietly if the targeted application is hung. So SendMessageTimeout() is perfect for our purpouse. See the sample code snippet below.

DWORD Result = 0;
LRESULT Return = 0;

// Handle of application window.
// Get it by using FindWindowEx function.
// Here for compilation, i get the handle of my dialog.
HWND hWnd = GetSafeHwnd(); 

// Send the NULL message to the window.
// SMTO_ABORTIFHUNG is specified to return immediately,
// if the process is hung.
Return = ::SendMessageTimeout( hWnd, // Window Handle
                               WM_NULL, // Message
                               0,       // WParam
                               0,       // LParam
                               SMTO_ABORTIFHUNG, // Flags
                               500,              // Timeout
                               &Result );        // Result

// Check whether the WM_NULL message is processed.
if( !Return )
{
    // Since the WM_NULL message is not processed,
    // the targeted window is hung. Forget about it!
}

Customize it according to your wish.


Just like null checking the pointer, you can check, whether a window is perfect by sending WM_NULL message.


Targeted Audience – Intermediate.





Expand/Collapse System Notification Area programmatically.

9 04 2008


Windows system task bar have System notification area. There is an arrow button nearby that by which we can Expand or collapse the System notification Area. Did you notice that while minimizing yahoo messenger, it displays a message that “Yahoo messenger will be still running in the system tray”. While displaying such as message, it will be nice to animate the Notification area by expanding and collapsing it.


See the code snippet. I guess, its self explanatory.

// Find the Shell Tray Window.
HWND hTrayWnd = ::FindWindowEx( 0,
                                0,
                                _T("Shell_TrayWnd"),
                                _T(""));
// Find the Tray notification window,
// which is a child of ShellTrayWidnow.
HWND hTrayNotifyWnd = ::FindWindowEx( hTrayWnd,
                                      0,
                                      _T("TrayNotifyWnd"),
                                      _T(""));
// Find the Button which is a child of ShellTrayWidnow.
HWND hButton = ::FindWindowEx( hTrayNotifyWnd,
                               0,
                              _T("Button"),
                              _T(""));

// Now get the DialogControlID of the button.
UINT DlgId = ::GetDlgCtrlID( hButton );

// Send a WM_COMMAND message, so the button reacts.
::SendMessage( hTrayNotifyWnd, WM_COMMAND, DlgId, 0 );

// Wait a bit to have an animation effect.
Sleep( 1000 );

// Send WM_COMMAND message once again.
::SendMessage( hTrayNotifyWnd, WM_COMMAND, DlgId, 0 );


Targeted Audiance – Intermediate