Solved

Graphics in Combobox

Posted on 1997-06-20
1
715 Views
Last Modified: 2008-02-26
How do I insert graphics in a ComboBox (list)? I want to be able to insert different colored boxes and special figures to allow the use to select their own symbol and color.
0
Comment
Question by:wdweldon
1 Comment
 
LVL 3

Accepted Solution

by:
dansari earned 100 total points
Comment Utility
You'll have to make the combo box owner-drawn - here is some of the Win32 on-line help on this (the example is an owner-drawn combo box with bitmaps and a name for each item.

If you're using < VB5, you'll need to use a subclassing control such as MessageBlaster or SpyWorks (Desaware) to subclass the combo box; if you're using VB5, you should use AddressOf together with a window procedure for the combo box.

Also, you'll need to change the style of the combo box to owner-draw, using SetWindowLong.

Here's the help (you can investigate further at www.microsoft.com/msdn/ if you don't already have the Win32 SDK):

Processing the WM_INITDIALOG and WM_DESTROY Messages in an Owner-Drawn Dialog Box
When you use a combo box in a dialog box, you usually respond to a WM_INITDIALOG message by initializing the combo box. The example in Creating a Square Meal Dialog Box loads the bitmaps used for the owner-drawn combo box, then calls the application-defined InitGroupList function to initialize the combo box. It also selects the first list item in the combo box, then calls the application-defined InitFoodList function to initialize the list box.
In the example, the owner-drawn combo box is a drop-down list box containing the names of each of the four food groups. InitGroupList adds the name of each food group, and calls the application-defined SetItemData function to associate a constant with each list item that identifies a corresponding food group.
The list box in the example contains the names of foods in the selected food group. InitFoodList resets the contents of the list box, then adds the names of the current food selection in the current food group drop-down list box.
The dialog box procedure processes the WM_DESTROY message to delete the bitmaps in the owner-drawn combo box.
Processing the WM_MEASUREITEM Message
An owner-drawn combo box sends the WM_MEASUREITEM message to its parent window or dialog box procedure so the application can set the dimensions of each list item. Because the example combo box has the CBS_OWNERDRAWFIXED style, the system sends the WM_MEASUREITEM message only once. Combo boxes with the CBS_OWNERDRAWVARIABLE style send a WM_MEASUREITEM message for each list item.
The lParam parameter points to a MEASUREITEMSTRUCT structure that identifies the control and list item. It also contains the default dimensions of the list item. The example in Creating a Square Meal Dialog Box modifies the itemHeight structure member to ensure that the list items are high enough to accommodate the food-group bitmaps.
Processing the WM_DRAWITEM Message
An owner-drawn combo box sends the WM_DRAWITEM message to its parent window or dialog box procedure each time the application must repaint a list item. The lParam parameter points to a DRAWITEMSTRUCT structure that identifies the control and list item. It also contains information needed to paint the item.
The example in Creating a Square Meal Dialog Box displays the list-item text and the bitmap associated with the food group. If the item has the focus, it also draws a focus rectangle. Before displaying the text, the example sets the foreground and background colors, based on the item selected. Because the combo box has the CBS_HASSTRINGS style, the combo box maintains the text for each list item that can be retrieved using the CB_GETLBTEXT message.
The bitmaps used for the list item depend on the food group. InitGroupList uses the CB_SETITEMDATA message to associate a constant with each list item, identifying the corresponding food group. The window procedure uses this value, contained in the itemData member of the DRAWITEMSTRUCT structure, to determine which bitmaps to display. The system uses two bitmaps for each food group symbol: a monochrome bitmap with the SRCAND raster operation to erase the irregular region behind the image, and a color bitmap with the SRCPAINT raster operation to paint the image.
Processing the WM_COMMAND Message in an Owner-Drawn Dialog Box
When an event occurs in a dialog box control, the control notifies the dialog box procedure by means of a WM_COMMAND message. The example in Creating a Square Meal Dialog Box processes notification messages from the combo box, the list box, and the OK button. The control identifier is in the low-order word of wParam, and the notification message is in the high-order word of wParam.
If the control identifier is IDCOMBO, an event has occurred in the combo box. In response, the dialog box procedure ignores all other combo box events except CBN_SELENDOK, which indicates that a selection was made, the drop down was closed up, and the changes made should be accepted. The dialog box procedure calls InitFoodList to reset the contents of the list box and to add the names of the current selection in the drop-down list box.
If the control identifier is IDLIST, an event has occurred in the list box. This causes the dialog box procedure to ignore all list box events except LBN_DBLCLK, which indicates that the user has double-clicked a list item. This event is processed in the same way as if an OK button has been chosen.
If the control identifier is IDOK, the user has chosen the OK button. In response, the dialog box procedure inserts the name of the selected food into the application's multiline edit control, then calls the EndDialog function to close the dialog box.
If the control identifier is IDCANCEL, the user has clicked the Cancel button. In response, the dialog box procedure calls EndDialog to close the dialog box.
Creating a Square Meal Dialog Box
Following are the dialog box procedure and supporting functions for the Square Meal dialog box.
 
HWND hwndMain;
HWND hwndEdit;
char achTemp[256];       /* temporary buffer            */
 
HBITMAP hbmBread;
HBITMAP hbmDairy;
HBITMAP hbmFruit;
HBITMAP hbmMeat;
HBITMAP hbmBreadMask;
HBITMAP hbmDairyMask;
HBITMAP hbmFruitMask;
HBITMAP hbmMeatMask;
 
/********************************************************
 
    FUNCTION:   FoodDlgProc
 
    PURPOSE:    Dialog procedure for Food dialog box.
 
*********************************************************/
 
BOOL CALLBACK FoodDlgProc(hwndDlg, msg, wParam, lParam)
HWND hwndDlg;
UINT msg;
WPARAM wParam;
LPARAM lParam;
{
    LPMEASUREITEMSTRUCT lpmis;
    LPDRAWITEMSTRUCT lpdis;
    HBITMAP hbmIcon;
    HBITMAP hbmMask;
    COLORREF clrBackground;
    COLORREF clrForeground;
    TEXTMETRIC tm;
    HDC hdc;
    HWND hwnd;
    int x;
    int y;
 
    switch (msg) {
        case WM_INITDIALOG:
 
            /*
             * Call an application-defined function to load
             * bitmap resources.
             */
 
            if (!LoadIconBitmaps()) {
                EndDialog(hwndDlg, -1);
                break;
            }
 
            /* Initialize the drop-down list box. */
 
            if (!InitGroupList(hwndDlg)) {
                DeleteIconBitmaps();
                EndDialog(hwndDlg, -1);
                break;
            }
 
            /* Select the first food group. */
 
            SendDlgItemMessage(hwndDlg, IDCOMBO, CB_SETCURSEL,
                0, 0);
 
            /* List the foods and select the first food. */
 
            InitFoodList(hwndDlg);
            SendDlgItemMessage(hwndDlg, IDLIST, LB_SETCURSEL,
                0, 0);
            break;
 
        case WM_MEASUREITEM:
            lpmis = (LPMEASUREITEMSTRUCT) lParam;
 
            if (lpmis->itemHeight < CY_BITMAP + 2)
                lpmis->itemHeight = CY_BITMAP + 2;
 
            break;
 
        case WM_DRAWITEM:
            lpdis = (LPDRAWITEMSTRUCT) lParam;
            if (lpdis->itemID == -1)            /* empty item */
                break;
 
            /* Determine the bitmaps used to draw the icon. */
 
            switch (lpdis->itemData) {
                case ID_BREAD:
                    hbmIcon = hbmBread;
                    hbmMask = hbmBreadMask;
                    break;
 
                case ID_DAIRY:
                    hbmIcon = hbmDairy;
                    hbmMask = hbmDairyMask;
                    break;
 
                case ID_FRUIT:
                    hbmIcon = hbmFruit;
                    hbmMask = hbmFruitMask;
                    break;
 
                default:                /* meat */
                    hbmIcon = hbmMeat;
                    hbmMask = hbmMeatMask;
                    break;
            }
 
            /*
             * The colors depend on whether the item is
             * selected.
             */
 
            clrForeground = SetTextColor(lpdis->hDC,
                GetSysColor(lpdis->itemState & ODS_SELECTED ?
                COLOR_HIGHLIGHTTEXT : COLOR_WINDOWTEXT));
 
            clrBackground = SetBkColor(lpdis->hDC,
                GetSysColor(lpdis->itemState & ODS_SELECTED ?
                COLOR_HIGHLIGHT : COLOR_WINDOW));
 
            /* Calculate the vertical and horizontal position. */
 
            GetTextMetrics(lpdis->hDC, &tm);
            y = (lpdis->rcItem.bottom + lpdis->rcItem.top -
                tm.tmHeight) / 2;
            x = LOWORD(GetDialogBaseUnits()) / 4;
 
            /* Get and display the text for the list item. */
 
            SendMessage(lpdis->hwndItem, CB_GETLBTEXT,
                lpdis->itemID, (LPARAM) (LPCSTR) achTemp);
 
            ExtTextOut(lpdis->hDC, CX_BITMAP + 2 * x, y,
                ETO_CLIPPED | ETO_OPAQUE, &lpdis->rcItem,
                achTemp, lstrlen(achTemp), NULL);
 
            /* Restore the previous colors. */
 
            SetTextColor(lpdis->hDC, clrForeground);
            SetBkColor(lpdis->hDC, clrBackground);
 
            /* Show the icon. */
 
            hdc = CreateCompatibleDC(lpdis->hDC);
            if (hdc == NULL)
                break;
 
            SelectObject(hdc, hbmMask);
            BitBlt(lpdis->hDC, x, lpdis->rcItem.top + 1,
                CX_BITMAP, CY_BITMAP, hdc, 0, 0, SRCAND);
 
            SelectObject(hdc, hbmIcon);
            BitBlt(lpdis->hDC, x, lpdis->rcItem.top + 1,
                CX_BITMAP, CY_BITMAP, hdc, 0, 0, SRCPAINT);
 
            DeleteDC(hdc);
 
            /* If the item has the focus, draw focus rectangle. */
 
            if (lpdis->itemState & ODS_FOCUS)
                DrawFocusRect(lpdis->hDC, &lpdis->rcItem);
 
            break;
 
        case WM_COMMAND:
            switch (LOWORD(wParam)) {
                case IDCOMBO:
                    if (HIWORD(wParam) == CBN_SELENDOK) {
                        InitFoodList(hwndDlg);
                        SendDlgItemMessage(hwndDlg, IDLIST,
                            LB_SETCURSEL, 0, 0);
                    }
                    break;
 
                case IDLIST:
                    if (HIWORD(wParam) != LBN_DBLCLK)
                        break;
 
                    /* For a double-click, process the OK case. */
 
                case IDOK:
 
                    /* Get the text for the selected list item. */
 
                    hwnd = GetDlgItem(hwndDlg, IDLIST);
                    SendMessage(hwnd, LB_GETTEXT,
                        SendMessage(hwnd, LB_GETCURSEL, 0, 0),
                        (LPARAM) achTemp);
 
                    /* Insert the text into the edit window. */
 
                    SendMessage(hwndEdit, EM_REPLACESEL, 0,
                        (LPARAM) achTemp);
 
                    EndDialog(hwndDlg, 0);
                    break;
 
                case IDCANCEL:
                    hwnd = GetDlgItem(hwndDlg, IDCOMBO);
                    if (SendMessage(hwnd, CB_GETDROPPEDSTATE,
                            0, 0))
                        SendMessage(hwnd, CB_SHOWDROPDOWN,
                            FALSE, 0);
                    else
                        EndDialog(hwndDlg, 0);
            }
            break;
 
        case WM_DESTROY:
 
            /*
             * Call the application-defined function to free
             * bitmap resources.
             */
 
            DeleteIconBitmaps();
            break;
 
        default:
            return FALSE;
    }
    return TRUE;
}
 
 
/********************************************************
 
    FUNCTION:   InitGroupList
 
    PURPOSE:    Initializes the "food groups" drop-down
                list box.
 
    COMMENTS:   The ID of the food group associated with
                each list item is saved as item data.
 
*********************************************************/
 
BOOL PASCAL InitGroupList(HWND hwndDlg)
{
    HWND hwndCombo = GetDlgItem(hwndDlg, IDCOMBO);
    DWORD dwIndex;
 
    /* Add an item for each food group. */
 
    LoadString(hinst, ID_BREAD, achTemp, sizeof(achTemp));
    dwIndex = SendMessage(hwndCombo, CB_ADDSTRING, 0,
        (LPARAM) (LPCSTR) achTemp);
    SendMessage(hwndCombo, CB_SETITEMDATA, dwIndex, ID_BREAD);
 
    LoadString(hinst, ID_DAIRY, achTemp, sizeof(achTemp));
    dwIndex = SendMessage(hwndCombo, CB_ADDSTRING, 0,
        (LPARAM) (LPCSTR) achTemp);
    SendMessage(hwndCombo, CB_SETITEMDATA, dwIndex, ID_DAIRY);
 
    LoadString(hinst, ID_FRUIT, achTemp, sizeof(achTemp));
    dwIndex = SendMessage(hwndCombo, CB_ADDSTRING, 0,
        (LPARAM) (LPCSTR) achTemp);
    SendMessage(hwndCombo, CB_SETITEMDATA, dwIndex, ID_FRUIT);
 
    LoadString(hinst, ID_MEAT, achTemp, sizeof(achTemp));
    dwIndex = SendMessage(hwndCombo, CB_ADDSTRING, 0,
        (LPARAM) (LPCSTR) achTemp);
    SendMessage(hwndCombo, CB_SETITEMDATA, dwIndex, ID_MEAT);
 
    return TRUE;
}
 
 
/********************************************************
 
    FUNCTION:   InitFoodList
 
    PURPOSE:    Clears the contents of the food list, and
                adds the names of foods for the current
                food group.
 
*********************************************************/
 
void PASCAL InitFoodList(HWND hwndDlg)
{
    HWND hwndCombo = GetDlgItem(hwndDlg, IDCOMBO);
    HWND hwndList = GetDlgItem(hwndDlg, IDLIST);
    UINT idFoodGroup;
    LPSTR lpsz;
    LPSTR lpszEnd;
 
    /* Determine the current food group. */
 
    idFoodGroup = SendMessage(
        hwndCombo,
        CB_GETITEMDATA,
        SendMessage(hwndCombo, CB_GETCURSEL, 0, 0),
        0
    );
 
    /* Clear the list contents. */
 
    SendMessage(hwndList, LB_RESETCONTENT, 0, 0);
 
    .
    .   /* Add food names for the current food group. */
    .
 
}
 
If you need more help, you can reach me at daniel@cherniak.on.ca.
0

Featured Post

Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

Join & Write a Comment

The debugging module of the VB 6 IDE can be accessed by way of the Debug menu item. That menu item can normally be found in the IDE's main menu line as shown in this picture.   There is also a companion Debug Toolbar that looks like the followin…
When designing a form there are several BorderStyles to choose from, all of which can be classified as either 'Fixed' or 'Sizable' and I'd guess that 'Fixed Single' or one of the other fixed types is the most popular choice. I assume it's the most p…
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…
Get people started with the utilization of class modules. Class modules can be a powerful tool in Microsoft Access. They allow you to create self-contained objects that encapsulate functionality. They can easily hide the complexity of a process from…

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now