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         SetWindowLongPtr(pChildWnd->hWnd, GWLP_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, (LPARAM)&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, (LPARAM)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 
376