- Fix KiDispatchException to unmask KI_EXCEPTION_INTERNAL when setting the exception...
[reactos.git] / rosapps / templates / mdi / framewnd.c
1 /*
2 * ReactOS Application
3 *
4 * framewnd.c
5 *
6 * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #ifdef _MSC_VER
24 #include "stdafx.h"
25 #else
26 #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
27 #include <windows.h>
28 #include <commctrl.h>
29 #include <stdlib.h>
30 #include <malloc.h>
31 #include <memory.h>
32 #include <tchar.h>
33 #include <process.h>
34 #include <stdio.h>
35 #endif
36
37 #include "main.h"
38 #include "about.h"
39 #include "framewnd.h"
40
41
42 ////////////////////////////////////////////////////////////////////////////////
43 // Global Variables:
44 //
45
46 BOOL bInMenuLoop = FALSE; // Tells us if we are in the menu loop
47
48 ////////////////////////////////////////////////////////////////////////////////
49 // Local module support methods
50 //
51
52 static void resize_frame_rect(HWND hWnd, PRECT prect)
53 {
54 RECT rt;
55
56 if (IsWindowVisible(hToolBar)) {
57 SendMessage(hToolBar, WM_SIZE, 0, 0);
58 GetClientRect(hToolBar, &rt);
59 prect->top = rt.bottom+3;
60 prect->bottom -= rt.bottom+3;
61 }
62 if (IsWindowVisible(hStatusBar)) {
63 int parts[] = {300, 500};
64
65 SendMessage(hStatusBar, WM_SIZE, 0, 0);
66 SendMessage(hStatusBar, SB_SETPARTS, 2, (LPARAM)&parts);
67 GetClientRect(hStatusBar, &rt);
68 prect->bottom -= rt.bottom;
69 }
70 MoveWindow(hMDIClient, prect->left-1,prect->top-1,prect->right+2,prect->bottom+1, TRUE);
71 }
72
73 static void resize_frame(HWND hWnd, int cx, int cy)
74 {
75 RECT rect = {0, 0, cx, cy};
76
77 resize_frame_rect(hWnd, &rect);
78 }
79
80 void resize_frame_client(HWND hWnd)
81 {
82 RECT rect;
83
84 GetClientRect(hWnd, &rect);
85 resize_frame_rect(hWnd, &rect);
86 }
87
88 ////////////////////////////////////////////////////////////////////////////////
89 static HHOOK hcbthook;
90 static ChildWnd* newchild = NULL;
91
92 LRESULT CALLBACK CBTProc(int code, WPARAM wParam, LPARAM lParam)
93 {
94 if (code == HCBT_CREATEWND && newchild) {
95 ChildWnd* pChildWnd = newchild;
96 newchild = NULL;
97 pChildWnd->hWnd = (HWND)wParam;
98 SetWindowLong(pChildWnd->hWnd, GWL_USERDATA, (LPARAM)pChildWnd);
99 }
100 return CallNextHookEx(hcbthook, code, wParam, lParam);
101 }
102
103 #if 0
104 HWND create_child_window(ChildWnd* pChildWnd)
105 {
106 MDICREATESTRUCT mcs = {
107 szChildClass, (LPTSTR)pChildWnd->path, hInst,
108 pChildWnd->pos.rcNormalPosition.left, pChildWnd->pos.rcNormalPosition.top,
109 pChildWnd->pos.rcNormalPosition.right-pChildWnd->pos.rcNormalPosition.left,
110 pChildWnd->pos.rcNormalPosition.bottom-pChildWnd->pos.rcNormalPosition.top,
111 0/*style*/, 0/*lParam*/
112 };
113 hcbthook = SetWindowsHookEx(WH_CBT, CBTProc, 0, GetCurrentThreadId());
114 newchild = pChildWnd;
115 pChildWnd->hWnd = (HWND)SendMessage(hMDIClient, WM_MDICREATE, 0, (LPARAM)&mcs);
116 if (!pChildWnd->hWnd)
117 return 0;
118 UnhookWindowsHookEx(hcbthook);
119 return pChildWnd->hWnd;
120 }
121
122 #endif
123
124
125 void toggle_child(HWND hWnd, UINT cmd, HWND hchild)
126 {
127 BOOL vis = IsWindowVisible(hchild);
128
129 HMENU hMenuOptions = GetSubMenu(hMenuFrame, ID_OPTIONS_MENU);
130 CheckMenuItem(hMenuOptions, cmd, vis?MF_BYCOMMAND:MF_BYCOMMAND|MF_CHECKED);
131 ShowWindow(hchild, vis?SW_HIDE:SW_SHOW);
132 resize_frame_client(hWnd);
133 }
134
135
136 static HWND InitChildWindow(LPTSTR param)
137 {
138 //TCHAR drv[_MAX_DRIVE];
139 TCHAR path[MAX_PATH];
140 ChildWnd* pChildWnd = NULL;
141 /*
142 LPCTSTR root = Globals.drives;
143 int i;
144 for(i = cmd - ID_DRIVE_FIRST; i--; root++)
145 while(*root)
146 root++;
147 if (activate_drive_window(root))
148 return 0;
149 _tsplitpath(root, drv, 0, 0, 0);
150 if (!SetCurrentDirectory(drv)) {
151 display_error(hWnd, GetLastError());
152 return 0;
153 }
154 */
155 GetCurrentDirectory(MAX_PATH, path);
156 // pChildWnd = alloc_child_window(path);
157 // if (!create_child_window(pChildWnd))
158 // free(pChildWnd);
159 pChildWnd = (ChildWnd*)malloc(sizeof(ChildWnd));
160 if (pChildWnd != NULL) {
161 MDICREATESTRUCT mcs = {
162 szChildClass, path, hInst,
163 CW_USEDEFAULT, CW_USEDEFAULT,
164 CW_USEDEFAULT, CW_USEDEFAULT,
165 0/*style*/, 0/*lParam*/
166 };
167 memset(pChildWnd, 0, sizeof(ChildWnd));
168 lstrcpy(pChildWnd->szPath, path);
169 pChildWnd->pos.length = sizeof(WINDOWPLACEMENT);
170 pChildWnd->pos.flags = 0;
171 pChildWnd->pos.showCmd = SW_SHOWNORMAL;
172 pChildWnd->pos.rcNormalPosition.left = CW_USEDEFAULT;
173 pChildWnd->pos.rcNormalPosition.top = CW_USEDEFAULT;
174 pChildWnd->pos.rcNormalPosition.right = CW_USEDEFAULT;
175 pChildWnd->pos.rcNormalPosition.bottom = CW_USEDEFAULT;
176 pChildWnd->nFocusPanel = 0;
177 pChildWnd->nSplitPos = 200;
178 hcbthook = SetWindowsHookEx(WH_CBT, CBTProc, 0, GetCurrentThreadId());
179 newchild = pChildWnd;
180 pChildWnd->hWnd = (HWND)SendMessage(hMDIClient, WM_MDICREATE, 0, (LPARAM)&mcs);
181 UnhookWindowsHookEx(hcbthook);
182 if (pChildWnd->hWnd == NULL) {
183 free(pChildWnd);
184 newchild = pChildWnd = NULL;
185 }
186 return pChildWnd->hWnd;
187 }
188 return 0;
189 }
190
191 BOOL CALLBACK CloseEnumProc(HWND hWnd, LPARAM lParam)
192 {
193 if (!GetWindow(hWnd, GW_OWNER)) {
194 SendMessage(GetParent(hWnd), WM_MDIRESTORE, (WPARAM)hWnd, 0);
195 if (SendMessage(hWnd, WM_QUERYENDSESSION, 0, 0)) {
196 SendMessage(GetParent(hWnd), WM_MDIDESTROY, (WPARAM)hWnd, 0);
197 }
198 }
199 return 1;
200 }
201
202 void OnEnterMenuLoop(HWND hWnd)
203 {
204 int nParts;
205
206 // Update the status bar pane sizes
207 nParts = -1;
208 SendMessage(hStatusBar, SB_SETPARTS, 1, (long)&nParts);
209 bInMenuLoop = TRUE;
210 SendMessage(hStatusBar, SB_SETTEXT, (WPARAM)0, (LPARAM)_T(""));
211 }
212
213 void OnExitMenuLoop(HWND hWnd)
214 {
215 RECT rc;
216 int nParts[3];
217
218 bInMenuLoop = FALSE;
219 // Update the status bar pane sizes
220 GetClientRect(hWnd, &rc);
221 nParts[0] = 100;
222 nParts[1] = 210;
223 nParts[2] = rc.right;
224 SendMessage(hStatusBar, SB_SETPARTS, 3, (long)nParts);
225 SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)_T(""));
226 UpdateStatusBar();
227 }
228
229 void OnMenuSelect(HWND hWnd, UINT nItemID, UINT nFlags, HMENU hSysMenu)
230 {
231 TCHAR str[100];
232
233 strcpy(str, TEXT(""));
234 if (nFlags & MF_POPUP) {
235 if (hSysMenu != GetMenu(hWnd)) {
236 if (nItemID == 2) nItemID = 5;
237 }
238 }
239 if (LoadString(hInst, nItemID, str, 100)) {
240 // load appropriate string
241 LPTSTR lpsz = str;
242 // first newline terminates actual string
243 lpsz = _tcschr(lpsz, '\n');
244 if (lpsz != NULL)
245 *lpsz = '\0';
246 }
247 SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)str);
248 }
249
250 ////////////////////////////////////////////////////////////////////////////////
251 //
252 // FUNCTION: _CmdWndProc(HWND, unsigned, WORD, LONG)
253 //
254 // PURPOSE: Processes WM_COMMAND messages for the main frame window.
255 //
256 //
257
258 LRESULT _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
259 {
260 HWND hChildWnd;
261
262 if (1) {
263
264 switch (LOWORD(wParam)) {
265 case ID_WINDOW_CLOSEALL:
266 EnumChildWindows(hMDIClient, &CloseEnumProc, 0);
267 break;
268 case ID_WINDOW_CLOSE:
269 hChildWnd = (HWND) SendMessage(hMDIClient, WM_MDIGETACTIVE, 0, 0);
270 if (!SendMessage(hChildWnd, WM_QUERYENDSESSION, 0, 0))
271 SendMessage(hMDIClient, WM_MDIDESTROY, (WPARAM)hChildWnd, 0);
272 break;
273 case ID_FILE_EXIT:
274 SendMessage(hWnd, WM_CLOSE, 0, 0);
275 break;
276 case ID_OPTIONS_TOOLBAR:
277 toggle_child(hWnd, LOWORD(wParam), hToolBar);
278 break;
279 case ID_OPTIONS_STATUSBAR:
280 toggle_child(hWnd, LOWORD(wParam), hStatusBar);
281 break;
282
283 case ID_FILE_OPEN:
284 case ID_WINDOW_NEW_WINDOW:
285 InitChildWindow("Child Window");
286 return 0;
287 case ID_WINDOW_CASCADE:
288 SendMessage(hMDIClient, WM_MDICASCADE, 0, 0);
289 break;
290 case ID_WINDOW_TILE_HORZ:
291 SendMessage(hMDIClient, WM_MDITILE, MDITILE_HORIZONTAL, 0);
292 break;
293 case ID_WINDOW_TILE_VERT:
294 SendMessage(hMDIClient, WM_MDITILE, MDITILE_VERTICAL, 0);
295 break;
296 case ID_WINDOW_ARRANGE_ICONS:
297 SendMessage(hMDIClient, WM_MDIICONARRANGE, 0, 0);
298 break;
299 case ID_HELP_ABOUT:
300 ShowAboutBox(hWnd);
301 break;
302 default:
303 hChildWnd = (HWND)SendMessage(hMDIClient, WM_MDIGETACTIVE, 0, 0);
304 if (IsWindow(hChildWnd))
305 SendMessage(hChildWnd, WM_COMMAND, wParam, lParam);
306 else
307 return DefFrameProc(hWnd, hMDIClient, message, wParam, lParam);
308 }
309 }
310 return 0;
311 }
312
313 ////////////////////////////////////////////////////////////////////////////////
314 //
315 // FUNCTION: FrameWndProc(HWND, unsigned, WORD, LONG)
316 //
317 // PURPOSE: Processes messages for the main frame window.
318 //
319 // WM_COMMAND - process the application menu
320 // WM_DESTROY - post a quit message and return
321 //
322 //
323
324 LRESULT CALLBACK FrameWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
325 {
326 switch (message) {
327 case WM_CREATE:
328 {
329 HMENU hMenuWindow = GetSubMenu(hMenuFrame, GetMenuItemCount(hMenuFrame)-2);
330 CLIENTCREATESTRUCT ccs = { hMenuWindow, IDW_FIRST_CHILD };
331 #if 0
332 hMDIClient = CreateWindow(_T("MDICLIENT"), NULL,
333 WS_CHILD|WS_CLIPCHILDREN|WS_VISIBLE,
334 0, 0, 0, 0,
335 hWnd, (HMENU)1, hInst, &ccs);
336 #else
337 hMDIClient = CreateWindowEx(0, _T("MDICLIENT"), NULL,
338 // hMDIClient = CreateWindowEx(0, (LPCTSTR)(int)hChildWndClass, NULL,
339 WS_CHILD|WS_CLIPCHILDREN|WS_VSCROLL|WS_HSCROLL|WS_VISIBLE|WS_BORDER,
340 0, 0, 0, 0,
341 hWnd, (HMENU)0, hInst, &ccs);
342 #endif
343 }
344 break;
345 case WM_COMMAND:
346 return _CmdWndProc(hWnd, message, wParam, lParam);
347 break;
348 case WM_SIZE:
349 resize_frame_client(hWnd);
350 break;
351 case WM_ENTERMENULOOP:
352 OnEnterMenuLoop(hWnd);
353 break;
354 case WM_EXITMENULOOP:
355 OnExitMenuLoop(hWnd);
356 break;
357 case WM_MENUSELECT:
358 OnMenuSelect(hWnd, LOWORD(wParam), HIWORD(wParam), (HMENU)lParam);
359 break;
360 case WM_DESTROY:
361 PostQuitMessage(0);
362 break;
363 case WM_QUERYENDSESSION:
364 case WM_CLOSE:
365 SendMessage(hWnd, WM_COMMAND, ID_WINDOW_CLOSEALL, 0);
366 if (GetWindow(hMDIClient, GW_CHILD) != NULL)
367 return 0;
368 // else fall thru...
369 default:
370 return DefFrameProc(hWnd, hMDIClient, message, wParam, lParam);
371 }
372 return 0;
373 }
374
375