📄 app_four.html
字号:
going to be any good with no windows to act on. I've disabled all these items by defaultin the resource so that I don't need to add extra code to do it when the application first startsup.<PRE CLASS="SNIP">LRESULT CALLBACK MDIChildWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){ switch(msg) { case WM_CREATE: { HFONT hfDefault; HWND hEdit; // Create Edit Control hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "", WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL, 0, 0, 100, 100, hwnd, (HMENU)IDC_CHILD_EDIT, GetModuleHandle(NULL), NULL); if(hEdit == NULL) MessageBox(hwnd, "Could not create edit box.", "Error", MB_OK | MB_ICONERROR); hfDefault = GetStockObject(DEFAULT_GUI_FONT); SendMessage(hEdit, WM_SETFONT, (WPARAM)hfDefault, MAKELPARAM(FALSE, 0)); } break; case WM_MDIACTIVATE: { HMENU hMenu, hFileMenu; UINT EnableFlag; hMenu = GetMenu(g_hMainWindow); if(hwnd == (HWND)lParam) { //being activated, enable the menus EnableFlag = MF_ENABLED; } else { //being de-activated, gray the menus EnableFlag = MF_GRAYED; } EnableMenuItem(hMenu, 1, MF_BYPOSITION | EnableFlag); EnableMenuItem(hMenu, 2, MF_BYPOSITION | EnableFlag); hFileMenu = GetSubMenu(hMenu, 0); EnableMenuItem(hFileMenu, ID_FILE_SAVEAS, MF_BYCOMMAND | EnableFlag); EnableMenuItem(hFileMenu, ID_FILE_CLOSE, MF_BYCOMMAND | EnableFlag); EnableMenuItem(hFileMenu, ID_FILE_CLOSEALL, MF_BYCOMMAND | EnableFlag); DrawMenuBar(g_hMainWindow); } break; case WM_COMMAND: switch(LOWORD(wParam)) { case ID_FILE_OPEN: DoFileOpen(hwnd); break; case ID_FILE_SAVEAS: DoFileSave(hwnd); break; case ID_EDIT_CUT: SendDlgItemMessage(hwnd, IDC_CHILD_EDIT, WM_CUT, 0, 0); break; case ID_EDIT_COPY: SendDlgItemMessage(hwnd, IDC_CHILD_EDIT, WM_COPY, 0, 0); break; case ID_EDIT_PASTE: SendDlgItemMessage(hwnd, IDC_CHILD_EDIT, WM_PASTE, 0, 0); break; } break; case WM_SIZE: { HWND hEdit; RECT rcClient; // Calculate remaining height and size edit GetClientRect(hwnd, &rcClient); hEdit = GetDlgItem(hwnd, IDC_CHILD_EDIT); SetWindowPos(hEdit, NULL, 0, 0, rcClient.right, rcClient.bottom, SWP_NOZORDER); } return DefMDIChildProc(hwnd, msg, wParam, lParam); default: return DefMDIChildProc(hwnd, msg, wParam, lParam); } return 0;}</PRE><P>I've implemented the File Open and Save as commands, the <CODE>DoFileOpen()</CODE> and <CODE>DoFileSave()</CODE> are nearly the same as in previous examples with theID of the edit control changed, and additionally setting the title of the MDI Childto the filename.<P>The Edit commands are easy, because the edit control has built in support for them, we just tell it what to do.<P>Remember I mentioned that there are little things you need to remember or your application willbehave strangely? Note that I've called <CODE>DefMDIChildProc()</CODE> at the end of <CODE>WM_SIZE</CODE>, this is important otherwise the system wont' have a chance to do it's own processing on the message. You can look up <CODE>DefMDIChildProc()</CODE> in MSDNfor a list of the messages that it processes, and always be sure to pass them to it.<H3>Creating and Destroying Windows</H3>MDI Child windows are not created directly, isntead we send a <CODE>WM_MDICREATE</CODE> message to the client window telling it what kind of window we want by setting the members of an <CODE>MDICREATESTRUCT</CODE>. You can look up the various members of this struct in your documentation, they are fairly straight forward. The return value from the <CODE>WM_MDICREATE</CODE> message is the handle to the newly created window.<PRE CLASS="SNIP">HWND CreateNewMDIChild(HWND hMDIClient){ MDICREATESTRUCT mcs; HWND hChild; mcs.szTitle = "[Untitled]"; mcs.szClass = g_szChildClassName; mcs.hOwner = GetModuleHandle(NULL); mcs.x = mcs.cx = CW_USEDEFAULT; mcs.y = mcs.cy = CW_USEDEFAULT; mcs.style = MDIS_ALLCHILDSTYLES; hChild = (HWND)SendMessage(hMDIClient, WM_MDICREATE, 0, (LONG)&mcs); if(!hChild) { MessageBox(hMDIClient, "MDI Child creation failed.", "Oh Oh...", MB_ICONEXCLAMATION | MB_OK); } return hChild;}</PRE><P>One member of <CODE>MDICREATESTRUCT</CODE> that I didn't use that can be quite usefull isthe <CODE>lParam</CODE> member. This can be used to send any 32bit value (like a pointer) tothe child you are creating in order to provide it with any custom information you choose.In the <CODE>WM_CREATE</CODE> handler for your child window, the <CODE>lParam</CODE> value for the <CODE>WM_CREATE</CODE>message will point to a <CODE>CREATESTRUCT</CODE>. the <CODE>lpCreateParams</CODE> member of that structurewill point to the <CODE>MDICREATESTRUCT</CODE> you sent along with <CODE>WM_MDICREATE</CODE>. So in orderto access the <CODE>lParam</CODE> value from the Child window you need to do something likethis in the child window procedure...<PRE CLASS="SNIP"> case WM_CREATE: { CREATESTRUCT* pCreateStruct; MDICREATESTRUCT* pMDICreateStruct; pCreateStruct = (CREATESTRUCT*)lParam; pMDICreateStruct = (MDICREATESTRUCT*)pCreateStruct->lpCreateParams; /* pMDICreateStruct now points to the same MDICREATESTRUCT that you sent along with the WM_MDICREATE message and you can use it to access the lParam. */ } break;</PRE><P>If you don't want to bother with those two extra pointers you can access thelParam in one step with<CODE>((MDICREATESTRUCT*)((CREATESTRUCT*)lParam)->lpCreateParams)->lParam</CODE><P>Now we can implement the File commands on our menu in our Frame window procedure:<PRE CLASS="SNIP"> case ID_FILE_NEW: CreateNewMDIChild(g_hMDIClient); break; case ID_FILE_OPEN: { HWND hChild = CreateNewMDIChild(g_hMDIClient); if(hChild) { DoFileOpen(hChild); } } break; case ID_FILE_CLOSE: { HWND hChild = (HWND)SendMessage(g_hMDIClient, WM_MDIGETACTIVE,0,0); if(hChild) { SendMessage(hChild, WM_CLOSE, 0, 0); } } break;</PRE><P>We can also provide some default MDI processing of window arrangment for our Window menu,since MDI supports this itself it's not much work.<PRE CLASS="SNIP"> case ID_WINDOW_TILE: SendMessage(g_hMDIClient, WM_MDITILE, 0, 0); break; case ID_WINDOW_CASCADE: SendMessage(g_hMDIClient, WM_MDICASCADE, 0, 0); break;</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 + -