图标的代码相当简单,调用LoadImage()两次,装入了16*16和32*32两种大小的图标.我们这里不能用LoadIcon()因为它只能装入资源,而不能装入文件.我们把实例句柄参数写成了NULL因为我们不是从我们的模块装入资源,而且我们不用资源的标识而使用了我们要装入的图标文件名.最后我们传入了LR_LOADFROMFILE这个标志来指示我们需要这个函数将我们传入的字符串当作文件名而不是资源名字.
如果所有的调用都成功了我们就我在WM_SETICON的消息处理中把图标的句柄赋给我们的窗口,如果失败了则弹出一个对话框告诉我们出错了.
注意:如果我们要装入的图标文件不在程序现在的当前目錄则LoadImage()调用失败.如果你用VC++从IDE来运行程序的话,当前目錄就是你工程文件所在的目錄.如果你从Debug或Release目錄下用文件管理器或命令行运行的话,你就需要把你的图标文件拷进去样以使你的程序找到它.如果怎样还是出错,就在你的调用中指明图标的全路径,"c:\\path\\to\\icon.ico".
好的,现在我们有菜单了,我们让它做点事情.这很简单,我们就需要响应WM_COMMAND消息就行.我们也需要我们得到了哪个消息并做出相应的动作.现在我们的
WndProc()应该看起来像这样.
- LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
- {
- switch(msg)
- {
- case WM_CREATE:
- {
- HMENU hMenu, hSubMenu;
- HICON hIcon, hIconSm;
- hMenu = CreateMenu();
- hSubMenu = CreatePopupMenu();
- AppendMenu(hSubMenu, MF_STRING, ID_FILE_EXIT, "E&xit");
- AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "&File");
- hSubMenu = CreatePopupMenu();
- AppendMenu(hSubMenu, MF_STRING, ID_STUFF_GO, "&Go");
- AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "&Stuff");
- SetMenu(hwnd, hMenu);
- hIcon = (HICON)LoadImage(NULL, "icon1.ico", IMAGE_ICON, 32, 32,
- LR_LOADFROMFILE);
- if(hIcon)
- SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
- else
- MessageBox(hwnd, "Could not load large icon!", "Error", MB_OK |
- MB_ICONERROR);
- hIconSm = (HICON)LoadImage(NULL, "icon1.ico", IMAGE_ICON, 16, 16,
- LR_LOADFROMFILE);
- if(hIconSm)
- SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)hIconSm);
- else
- MessageBox(hwnd, "Could not load small icon!", "Error", MB_OK |
- MB_ICONERROR);
- }
- break;
- case WM_COMMAND:
- switch(LOWORD(wParam))
- {
- case ID_FILE_EXIT:
- PostMessage(hwnd,WM_CLOSE,NULL,NULL);
- break;
- case ID_STUFF_GO:
- MessageBox(hwnd,"you click the GO","Menu MessageBox",MB_OK | MB_ICONEXCLAMATION);
- break;
- }
- break;
- case WM_LBUTTONDOWN:
- {
- char szFileName[MAX_PATH];
- HINSTANCE hInstance = GetModuleHandle(NULL);
- GetModuleFileName(hInstance, szFileName, MAX_PATH);
- MessageBox(hwnd, szFileName, "This program is:", MB_OK |
- MB_ICONINFORMATION);
- }
- break;
- case WM_CLOSE:
- DestroyWindow(hwnd);
- break;
- case WM_DESTROY:
- PostQuitMessage(0);
- break;
- default:
- return DefWindowProc(hwnd, msg, wParam, lParam);
- }
- return 0;
- }
你可以看到我们把WM_COMMAND消息响应了,并且它还有自己的一个switch()在其中.这个switch()由wParm的低字来決定,因为可能WM_COMMAND消息包含了发送消息的菜单或控件的标识.
我们显然想要Exit菜单来关闭程序.所以在WM_COMMAND,ID_FILE_EXIT消息的处理程序中你可以使用下面的代码来做到这一点.PostMessage(hwnd,WM_CLOSE ,0, 0);
你的WM_COMMAND处理代码现在看起来应该像样:
- case WM_COMMAND:
- switch(LOWORD(wParam))
- {
- case ID_FILE_EXIT:
- PostMessage(hwnd, WM_CLOSE, 0, 0);
- break;
- case ID_STUFF_GO:
- break;
- }
- break;
函数LoadImage
函数功能:装载图标,光标,或位图。
函数原型:HANDLE LoadImage(NINSTANCE hinst,LPCTSTR lpszName,UINT uType,int
cxDesired,int CyDesired,UINT fuLoad);
(HBITMAP) LoadImage ( AfxGetInstanceHandle() , TEXT("c://*.bmp"), IMAGE_BITMAP,
0,0,LR_CREATEDIBSECTION|LR_LOADFROMFILE));
参数:
hinst:包含被装载图像模块的实例句柄。若要装载OEM图像,则设此参数值为0。
lpszName:如果hinst非NULL,而且参数fuLoad不包括LR_LOADFROMFILE时,那么lpszName是一个保留在hinst模块中的图像资源ID。
如果参数hinst为NULL,并且LR_LOADFROMFILE被指定,那么这个参数是被装载的OEM的图像标识。
如果参数fuLoad包含LR_LOADFROMFILE值,那么参数lpszName是图像文件路径。
uType:指定被装载图像类型 IMAGE_BITMAP IMAGE_CURSOR IMAGE_ICON 。
cx ,cy:图标或光标的宽度高度,如果参数为0,则fuLoad不设LR_DEFAULTSIZE,那么函数使用目前的资源高度。对静态位图来说,参数cx ,cy 为零。
fuLoad:LR_DEFAULTCOLOR:缺省标志;
LR_CREATEDIBSECTION:装载位图时,返回一个DIB部分位图,而不是DDB位图是装载位图,而不是映射位图到显示设备时用它;
LRDIFAULTSIZE:若装载光标或图标,cxDesired或cyDesired未被设为零,使用它;
LR_LOADFROMFILE:图像来自文件。若未标定,图像来自资源ID;
LR_MONOCHROME:装载黑白图;
LR_SHARED:共享内存,多次调用同一资源时不会再重新装载图像入内存。
注意:当使用完资源后,最好释放加速器表、位图、光标、图标以及菜单所占的内存资源。
加速器表:DesteoyAcceleratorTable;位图:DeleteObject;光标:DestroyCursor;
图标:Destroylcon;菜单:DestroyMenu