📄 window_click.html
字号:
<HTML><LINK HREF="style.css" REL="STYLESHEET" TYPE="text/css"><HEAD><TITLE>Tutorial: Handling Messages</TITLE></HEAD><BODY><FONT SIZE="-1">[ <A HREF="./index.html">contents</A>| <A HREF="http://www.winprog.org/">#winprog</A>]</FONT><HR><H1>Handling Messages</H1><P>Example: window_click</P><IMG SRC="images/window_click.gif" ALT="[images/window_click.gif]" ALIGN="right">Alright, we've got a window, but it doesn't do anything except what <CODE>DefWindowProc()</CODE>allows it to, like be sized, maximised, etc... Not really all that exciting.<P>In the next section I am going to show you how to modify what you already haveto do somehting new. This way I can just tell you <I>"Handle this message, anddo this in it..."</I> and you will know what I mean and be able to do so withoutseeing an entire example. That's the hope anyway, so pay attention :P<P>Okay for starters take the example code for the last window we worked on and make sure itcompiles and runs as expected. Then you can either keep working on it forthe next little bit or copy it to a new project to modify.<P>We're going to add the capability to show the user what the name of our program iswhen they click on our window. Not very exciting, it's basically to get thehang of handling messages. Lets look at what we have in our <CODE>WndProc()</CODE>:<PRE CLASS="SNIP">LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){ switch(msg) { case WM_CLOSE: DestroyWindow(hwnd); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hwnd, msg, wParam, lParam); } return 0;}</PRE>If we want to handle mouse clicks, we need to add a <CODE>WM_LBUTTONDOWN</CODE> handler(or <CODE>WM_RBUTTONDOWN</CODE>, <CODE>WM_MBUTTONDOWN</CODE>, for right and middle clicks respectively).<P>If I or someone else refers to <I>handling a message</I> they mean to add it into the <CODE>WndProc()</CODE>of your window class as follows:<PRE CLASS="SNIP">LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){ switch(msg) { case WM_LBUTTONDOWN: // <- // <- we just added this stuff break; // <- case WM_CLOSE: DestroyWindow(hwnd); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hwnd, msg, wParam, lParam); } return 0;}</PRE>The order in which you handle your messages rarely matters. Just make sureyou've got your <CODE>break;</CODE> after each one. As you can see we added another <CODE>case</CODE>into our <CODE>switch()</CODE>. Now we want something to happen when we get to this part ofour program.<P>First I will present the code we want to add (that will show the user thefilename of our program) and then I will integrate it into our program. Lateron I will probably just show you the code and let you integrate it into yourprogram. This is of course better for me as I don't have to type as much andit's better for you because you will be able to add the code into ANY programand not just the ones I present. <B>If you aren't sure how to do it, look at the example zipfile included with the section.</B><PRE CLASS="SNIP">GetModuleFileName(hInstance, szFileName, MAX_PATH);MessageBox(hwnd, szFileName, "This program is:", MB_OK | MB_ICONINFORMATION);</PRE>Now this code does not stand on it's own, it can't just be slapped into ourcode any old place. We specifically want it to run when the user clicks themouse button so this is how I would merge this small bit of code into ourskeleton program:<PRE CLASS="SNIP">LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){ switch(msg) { case WM_LBUTTONDOWN:// BEGIN NEW CODE { char szFileName[MAX_PATH]; HINSTANCE hInstance = GetModuleHandle(NULL); GetModuleFileName(hInstance, szFileName, MAX_PATH); MessageBox(hwnd, szFileName, "This program is:", MB_OK | MB_ICONINFORMATION); }// END NEW CODE break; case WM_CLOSE: DestroyWindow(hwnd); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hwnd, msg, wParam, lParam); } return 0;}</PRE><P>Note the new set of curly braces {} . These are required when declaring variables insidea <CODE>switch()</CODE> statement. This should be basic C knowledge but I thought I shouldpoint it out anyway for those of you doing things the hard way.<P>So if you've added in that code, compile it now. If it works, click on thewindow and you should see a box with the name of the .exe pop up.<P>You'll notice we've added two variables, <CODE>hInstance</CODE> and <CODE>szFileName</CODE>. Look up <CODE>GetModuleFileName()</CODE> and you will see that the first parameter is a <CODE>HINSTANCE</CODE>refering to the executable module (our program, the .exe file). Where do we get such a thing?<CODE>GetModuleHandle()</CODE> is the answer. The references for <CODE>GetModuleHandle()</CODE> indicatethat passing in NULL will return us "<I>a handle to the file used to create the calling process</I>", which isexactly what we need, the <CODE>HINSTANCE</CODE> just mentioned. Putting all this information togetherwe end up with the following declaration:<PRE CLASS="SNIP">HINSTANCE hInstance = GetModuleHandle(NULL);</PRE><P>Now on to the second parameter, again turning to our trusty reference manual, we see that itis "<I> a pointer to a buffer that receives the path and file name of the specified module</I>"and the data type is <CODE>LPTSTR</CODE> (or <CODE>LPSTR</CODE> if your references are old). Since <CODE>LPSTR</CODE> is equivalent to <CODE>char*</CODE> we can declare an array of <CODE>char</CODE>'slike this:<PRE CLASS="SNIP">char szFileName[MAX_PATH];</PRE><P><CODE>MAX_PATH</CODE> is a handy macro included via <CODE><windows.h></CODE> that is defined to the maximum lengthof a buffer needed to store a filename under Win32. We also pass <CODE>MAX_PATH</CODE> to <CODE>GetModuleFileName()</CODE>so it knows the size of the buffer.<P>After <CODE>GetModuleFileName()</CODE> is called, the buffer <CODE>szFileName</CODE> will be filled with a null terminated string containing the name of our .exe file. We pass thisvalue to <CODE>MessageBox()</CODE> as an easy way of displaying it to the user.<P>So if you've added in that code, compile it now. If it works, click on thewindow and you should see a box with the name of the .exe pop up.<P>If it doesn't work, here's the full code to the program. Compare it to whatyou have and see what, if any, mistakes you made.<PRE CLASS="LIST">#include <windows.h>const char g_szClassName[] = "myWindowClass";LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){ switch(msg) { 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;}int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){ WNDCLASSEX wc; HWND hwnd; MSG Msg; wc.cbSize = sizeof(WNDCLASSEX); wc.style = 0; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wc.lpszMenuName = NULL; wc.lpszClassName = g_szClassName; wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); if(!RegisterClassEx(&wc)) { MessageBox(NULL, "Window Registration Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK); return 0; } hwnd = CreateWindowEx( WS_EX_CLIENTEDGE, g_szClassName, "The title of my window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 240, 120, NULL, NULL, hInstance, NULL); if(hwnd == NULL) { MessageBox(NULL, "Window Creation Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK); return 0; } ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); while(GetMessage(&Msg, NULL, 0, 0) > 0) { TranslateMessage(&Msg); DispatchMessage(&Msg); } return Msg.wParam;}</PRE><HR><FONT SIZE="-1">Copyright © 1998-2003, Brook Miles (<A HREF="mailto:forger(nospam)winprog.org">theForger</A>). All rights reserved.</FONT><SCRIPT language="JavaScript"><!-- var re = /\(nospam\)/ig; var str; for(i = 0;i < document.links.length;i++) { str = "" + document.links(i).href; if(str.search(re) != -1) document.links(i).href = str.replace(re, "@"); str = "" + document.links(i).innerHTML; if(str.search(re) != -1) document.links(i).innerHTML = str.replace(re, "@"); }--></SCRIPT></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -