Home   Index   About
Ultimate Pack


Custom Search
Example of Using Custom Check-mark Bitmaps

The example in this topic assigns custom check-mark bitmaps to menu items in two menus. The menu items in the first menu specify character attributes: bold, italic, and underline. Each menu item can be either checked or unchecked. For these menu items, the example uses check-mark bitmaps that resemble the checked and unchecked states of a check box control.

The menu items in the second menu specify paragraph alignment settings: left, centered, and right. Only one of these menu items is checked at any given time. For these menu items, the example uses check-mark bitmaps that resemble the checked and unchecked states of a radio button control.

The window procedure processes the WM_CREATE message by calling the application-defined OnCreate function. OnCreate creates the four check-mark bitmaps and then assigns them to their appropriate menu items by using the SetMenuItemBitmaps function.

To create each bitmap, OnCreate calls the application-defined CreateMenuBitmaps function, specifying a pointer to a bitmap-specific drawing function. CreateMenuBitmaps creates a monochrome bitmap of the required size, selects it into a memory device context, and erases the background. Then it calls the specified drawing function to fill in the foreground.

The four application-defined drawing functions are DrawCheck, DrawUncheck, DrawRadioCheck, and DrawRadioUncheck. They draw a rectangle with an X, an empty rectangle, an ellipse containing a smaller filled ellipse, and an empty ellipse, respectively.

The window procedure processes the WM_DESTROY message by deleting the check-mark bitmaps. It retrieves each bitmap handle by using the GetMenuItemInfo function and then passes the handle to the DeleteObject function.

When the user chooses a menu item, a WM_COMMAND message is sent to the owner window. For menu items on the Character menu, the window procedure calls the application-defined CheckCharacterItem function. For items on the Paragraph menu, the window procedure calls the application-defined CheckParagraphItem function.

Each item on the Character menu can be checked and unchecked independently. Therefore, CheckCharacterItem simply switches the specified menu item's check state. First, the function calls the GetMenuItemInfo function to get the current menu item state. Then it switches the MFS_CHECKED state flag and sets the new state by calling the SetMenuItemInfo function.

Unlike character attributes, only one paragraph alignment can be selected at a time. Therefore, CheckParagraphItem checks the specified menu item and removes the check mark from all other items on the menu. To do so, it calls the CheckMenuRadioItem function.

Following are the relevant portions of the application's header file.

// Menu-item identifiers for the Character menu

#define IDM_CHARACTER 10

#define IDM_BOLD 11

#define IDM_ITALIC 12

#define IDM_UNDERLINE 13

// Menu-item identifiers for the Paragraph menu

#define IDM_PARAGRAPH 20

#define IDM_LEFT 21

#define IDM_CENTER 22

#define IDM_RIGHT 23

// Function-pointer type for drawing functions

typedef VOID (WINAPI * DRAWFUNC)(HDC hdc, SIZE size);

Following are the relevant portions of the application's window procedure and related functions.

LRESULT CALLBACK MainWindowProc(

HWND hwnd,

UINT uMsg,

WPARAM wParam,

LPARAM lParam

)

{

switch (uMsg) {

case WM_CREATE:

if (!OnCreate(hwnd))

return -1;

break;

case WM_DESTROY:

OnDestroy(hwnd);

PostQuitMessage(0);

break;

case WM_COMMAND:

switch (LOWORD(wParam)) {

case IDM_BOLD:

case IDM_ITALIC:

case IDM_UNDERLINE:

CheckCharacterItem(hwnd, LOWORD(wParam));

break;

case IDM_LEFT:

case IDM_CENTER:

case IDM_RIGHT:

CheckParagraphItem(hwnd, LOWORD(wParam));

break;

.

. // Process other commands here.

.

}

break;

.

. // Process other messages here.

.

default:

return DefWindowProc(hwnd, uMsg, wParam, lParam);

}

return 0;

}

VOID WINAPI CheckCharacterItem(HWND hwnd, UINT uID)

{

HMENU hmenuBar = GetMenu(hwnd);

HMENU hmenuPopup;

MENUITEMINFO mii;

// Get the handle of the Character menu.

mii.fMask = MIIM_SUBMENU; // information to get

GetMenuItemInfo(hmenuBar, IDM_CHARACTER, FALSE, &mii);

hmenuPopup = mii.hSubMenu;

// Get the state of the specified menu item.

mii.fMask = MIIM_STATE; // information to get

GetMenuItemInfo(hmenuPopup, uID, FALSE, &mii);

// Toggle the checked state.

mii.fState ^= MFS_CHECKED;

SetMenuItemInfo(hmenuPopup, uID, FALSE, &mii);

}

VOID WINAPI CheckParagraphItem(HWND hwnd, UINT uID)

{

HMENU hmenuBar = GetMenu(hwnd);

HMENU hmenuPopup;

MENUITEMINFO mii;

// Get the handle of the Paragraph menu.

mii.fMask = MIIM_SUBMENU; // information to get

GetMenuItemInfo(hmenuBar, IDM_PARAGRAPH, FALSE, &mii);

hmenuPopup = mii.hSubMenu;

// Check the specified item and uncheck all the others.

CheckMenuRadioItem(

hmenuPopup, // handle of menu

IDM_LEFT, // first item in range

IDM_RIGHT, // last item in range

uID, // item to check

MF_BYCOMMAND // IDs, not positions

);

}

BOOL WINAPI OnCreate(HWND hwnd)

{

HMENU hmenuBar = GetMenu(hwnd);

HMENU hmenuPopup;

MENUITEMINFO mii;

UINT uID;

HBITMAP hbmChecked;

HBITMAP hbmUnchecked;

// Get the handle of the Character menu.

mii.fMask = MIIM_SUBMENU; // information to get

GetMenuItemInfo(hmenuBar, IDM_CHARACTER, FALSE, &mii);

hmenuPopup = mii.hSubMenu;

// Create the checked and unchecked bitmaps.

hbmChecked = CreateMenuBitmap(DrawCheck);

hbmUnchecked = CreateMenuBitmap(DrawUncheck);

// Set the checkmark bitmaps for each menu item.

for (uID = IDM_BOLD; uID <= IDM_UNDERLINE; uID++) {

SetMenuItemBitmaps(hmenuPopup, uID, MF_BYCOMMAND,

hbmUnchecked, hbmChecked);

}

// Get the handle of the Paragraph pop-up menu.

mii.fMask = MIIM_SUBMENU; // information to get

GetMenuItemInfo(hmenuBar, IDM_PARAGRAPH, FALSE, &mii);

hmenuPopup = mii.hSubMenu;

// Create the checked and unchecked bitmaps.

hbmChecked = CreateMenuBitmap(DrawRadioCheck);

hbmUnchecked = CreateMenuBitmap(DrawRadioUncheck);

// Set the checkmark bitmaps for each menu item.

for (uID = IDM_LEFT; uID <= IDM_RIGHT; uID++) {

SetMenuItemBitmaps(hmenuPopup, uID, MF_BYCOMMAND,

hbmUnchecked, hbmChecked);

}

// Initially check the IDM_LEFT paragraph item.

CheckMenuRadioItem(hmenuPopup, IDM_LEFT, IDM_RIGHT,

IDM_LEFT, MF_BYCOMMAND);

return TRUE;

}

HBITMAP WINAPI CreateMenuBitmap(DRAWFUNC lpfnDraw)

{

// Create a DC compatible with the desktop window's DC.

HWND hwndDesktop = GetDesktopWindow();

HDC hdcDesktop = GetDC(hwndDesktop);

HDC hdcMem = CreateCompatibleDC(hdcDesktop);

// Determine the required bitmap size.

DWORD dwExt = GetMenuCheckMarkDimensions();

SIZE size = { LOWORD(dwExt), HIWORD(dwExt) };

// Create a monochrome bitmap and select it.

HBITMAP hbm = CreateBitmap(size.cx, size.cy, 1, 1, NULL);

HBITMAP hbmOld = SelectObject(hdcMem, hbm);

// Erase the background and call the drawing function.

PatBlt(hdcMem, 0, 0, size.cx, size.cy, WHITENESS);

(*lpfnDraw)(hdcMem, size);

// Clean up.

SelectObject(hdcMem, hbmOld);

DeleteDC(hdcMem);

ReleaseDC(hwndDesktop, hdcDesktop);

return hbm;

}

VOID WINAPI DrawCheck(HDC hdc, SIZE size)

{

HBRUSH hbrOld;

hbrOld = SelectObject(hdc, GetStockObject(NULL_BRUSH));

Rectangle(hdc, 0, 0, size.cx, size.cy);

MoveToEx(hdc, 0, 0, NULL);

LineTo(hdc, size.cx, size.cy);

MoveToEx(hdc, 0, size.cy - 1, NULL);

LineTo(hdc, size.cx - 1, 0);

SelectObject(hdc, hbrOld);

}

VOID WINAPI DrawUncheck(HDC hdc, SIZE size)

{

HBRUSH hbrOld;

hbrOld = SelectObject(hdc, GetStockObject(NULL_BRUSH));

Rectangle(hdc, 0, 0, size.cx, size.cy);

SelectObject(hdc, hbrOld);

}

VOID WINAPI DrawRadioCheck(HDC hdc, SIZE size)

{

HBRUSH hbrOld;

hbrOld = SelectObject(hdc, GetStockObject(NULL_BRUSH));

Ellipse(hdc, 0, 0, size.cx, size.cy);

SelectObject(hdc, GetStockObject(BLACK_BRUSH));

Ellipse(hdc, 2, 2, size.cx - 2, size.cy - 2);

SelectObject(hdc, hbrOld);

}

VOID WINAPI DrawRadioUncheck(HDC hdc, SIZE size)

{

HBRUSH hbrOld;

hbrOld = SelectObject(hdc, GetStockObject(NULL_BRUSH));

Ellipse(hdc, 0, 0, size.cx, size.cy);

SelectObject(hdc, hbrOld);

}

VOID WINAPI OnDestroy(HWND hwnd)

{

HMENU hmenuBar = GetMenu(hwnd);

HMENU hmenuPopup;

MENUITEMINFO mii;

// Get the handle of the Character menu.

mii.fMask = MIIM_SUBMENU; // information to get

GetMenuItemInfo(hmenuBar, IDM_CHARACTER, FALSE, &mii);

hmenuPopup = mii.hSubMenu;

// Get the check-mark bitmaps and delete them.

mii.fMask = MIIM_CHECKMARKS;

GetMenuItemInfo(hmenuPopup, IDM_BOLD, FALSE, &mii);

DeleteObject(mii.hbmpChecked);

DeleteObject(mii.hbmpUnchecked);

// Get the handle of the Paragraph menu.

mii.fMask = MIIM_SUBMENU; // information to get

GetMenuItemInfo(hmenuBar, IDM_PARAGRAPH, FALSE, &mii);

hmenuPopup = mii.hSubMenu;

// Get the check-mark bitmaps and delete them.

mii.fMask = MIIM_CHECKMARKS;

GetMenuItemInfo(hmenuPopup, IDM_LEFT, FALSE, &mii);

DeleteObject(mii.hbmpChecked);

DeleteObject(mii.hbmpUnchecked);

}


Last news from Greatis Software

Nostalgia .Net     Nostalgia .Net     .Net is powerful, but not all-powerful, so sometimes we need to use Win32 API for our .Net applications. It's simple enough with Platform Invoke if you have Win32 skill, but we do not always have time to dig the ancient documentation, declare the special types that are compatible with Win32, find the values of the Win32's constants and so on. Nostalgia .Net offers several simple-to-use classes, and components that will allow you to forget about the headache of Win32 and just use the power of Win32 in your application the same way as you use the native. Net classes.  More »

Recommended software for developers

Ultimate Pack for Delphi and C++ Builder     Ultimate Pack     Component pack for Delphi and C++ Builder that contains runtime form designer, runtime object inspector, print suite and much more for the very special price.  More »

Form Designer .Net     Form Designer .Net     Unique runtime form design solution that allows to edit any form in .Net WinForms application at runtime with full source codes for only 300 euro!  More »

Print Suite .Net     Print Suite .Net     Print Suite .Net is a set of components for easy printing texts, images and grids from your WinForms applications. Full C# source codes are available  More »

Gradient Controls .Net     Gradient Controls .Net     Gradient Controls .Net offers controls with gradient background feature. Labels, panels and so on... Full C# source codes are available  More »

iGrid     Greatis iGrid     iGrid plots drawing grid right over your desktop, so you can use it everywhere, with any drawing application without any special plugins for different graphic editors.  More »


All the contacts and projects

Dmitry Vasiliev (just.dmitry)

Related Links

Software for Visual Studio .NET developers
Software for Delphi and C++ Builder developers
Software for Visual Basic 6 developers
Delphi Tips&Tricks
MegaDetailed.NET

More Online Helps

Win32 Programmer's Reference
Win32 Multimedia Programmer's Reference
OLE Programmer's Reference
Microsoft Windows Pen API Programmer's Reference
Microsoft Windows Sockets 2 Reference
Microsoft Windows Telephony API (TAPI) Programmer's Reference
Unix Manual Pages

Free Tech Secrets ;) Copyright © 2008-2012 Free Tech Secrets ;) greatis just4fun network just4fun