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