6 * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
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.
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.
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.
26 #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
53 //#define COLOR_SPLITBAR WHITE_BRUSH
54 #define COLOR_SPLITBAR LTGRAY_BRUSH
56 #define COLOR_SPLITBAR LTGRAY_BRUSH
59 ////////////////////////////////////////////////////////////////////////////////
63 HWND hSplitWnd
; // Splitter Bar Control Window
66 ////////////////////////////////////////////////////////////////////////////////
67 // Local module support methods
70 #ifndef _NO_EXTENSIONS
72 void set_header(Pane
* pane
)
75 int scroll_pos
= GetScrollPos(pane
->hWnd
, SB_HORZ
);
78 item
.mask
= HDI_WIDTH
;
81 for(; x
+pane
->widths
[i
]<scroll_pos
&& i
<COLUMNS
; i
++) {
83 Header_SetItem(pane
->hwndHeader
, i
, &item
);
88 item
.cxy
= x
- scroll_pos
;
89 Header_SetItem(pane
->hwndHeader
, i
++, &item
);
91 for(; i
<COLUMNS
; i
++) {
92 item
.cxy
= pane
->widths
[i
];
94 Header_SetItem(pane
->hwndHeader
, i
, &item
);
99 static LRESULT
pane_notify(Pane
* pane
, NMHDR
* pnmh
)
105 HD_NOTIFY
* phdn
= (HD_NOTIFY
*) pnmh
;
106 int idx
= phdn
->iItem
;
107 int dx
= phdn
->pitem
->cxy
- pane
->widths
[idx
];
111 GetClientRect(pane
->hWnd
, &clnt
);
112 // move immediate to simulate HDS_FULLDRAG (for now [04/2000] not realy needed with WINELIB)
113 Header_SetItem(pane
->hwndHeader
, idx
, phdn
->pitem
);
114 pane
->widths
[idx
] += dx
;
115 for (i
= idx
; ++i
<= COLUMNS
; )
116 pane
->positions
[i
] += dx
;
118 int scroll_pos
= GetScrollPos(pane
->hWnd
, SB_HORZ
);
119 RECT rt_scr
= {pane
->positions
[idx
+1]-scroll_pos
, 0, clnt
.right
, clnt
.bottom
};
120 RECT rt_clip
= {pane
->positions
[idx
]-scroll_pos
, 0, clnt
.right
, clnt
.bottom
};
121 if (rt_scr
.left
< 0) rt_scr
.left
= 0;
122 if (rt_clip
.left
< 0) rt_clip
.left
= 0;
123 ScrollWindowEx(pane
->hWnd
, dx
, 0, &rt_scr
, &rt_clip
, 0, 0, SW_INVALIDATE
);
124 rt_clip
.right
= pane
->positions
[idx
+1];
125 RedrawWindow(pane
->hWnd
, &rt_clip
, 0, RDW_INVALIDATE
|RDW_UPDATENOW
);
126 if (pnmh
->code
== HDN_ENDTRACK
) {
127 ListBox_SetHorizontalExtent(pane
->hWnd
, pane
->positions
[COLUMNS
]);
128 if (GetScrollPos(pane
->hWnd
, SB_HORZ
) != scroll_pos
)
134 case HDN_DIVIDERDBLCLICK
:
136 HD_NOTIFY
* phdn
= (HD_NOTIFY
*) pnmh
;
138 calc_single_width(pane
, phdn
->iItem
);
139 item
.mask
= HDI_WIDTH
;
140 item
.cxy
= pane
->widths
[phdn
->iItem
];
141 Header_SetItem(pane
->hwndHeader
, phdn
->iItem
, &item
);
142 InvalidateRect(pane
->hWnd
, 0, TRUE
);
152 static BOOL
pane_command(Pane
* pane
, UINT cmd
)
156 if (pane
->visible_cols
) {
157 pane
->visible_cols
= 0;
158 calc_widths(pane
, TRUE
);
159 #ifndef _NO_EXTENSIONS
162 InvalidateRect(pane
->hWnd
, 0, TRUE
);
163 CheckMenuItem(Globals
.hMenuView
, ID_VIEW_NAME
, MF_BYCOMMAND
|MF_CHECKED
);
164 // CheckMenuItem(Globals.hMenuView, ID_VIEW_ALL_ATTRIBUTES, MF_BYCOMMAND);
165 // CheckMenuItem(Globals.hMenuView, ID_VIEW_SELECTED_ATTRIBUTES, MF_BYCOMMAND);
169 case ID_VIEW_ALL_ATTRIBUTES
:
170 if (pane
->visible_cols
!= COL_ALL
) {
171 pane
->visible_cols
= COL_ALL
;
172 calc_widths(pane
, TRUE
);
173 #ifndef _NO_EXTENSIONS
176 InvalidateRect(pane
->hWnd
, 0, TRUE
);
177 CheckMenuItem(Globals
.hMenuView
, ID_VIEW_NAME
, MF_BYCOMMAND
);
178 // CheckMenuItem(Globals.hMenuView, ID_VIEW_ALL_ATTRIBUTES, MF_BYCOMMAND|MF_CHECKED);
179 // CheckMenuItem(Globals.hMenuView, ID_VIEW_SELECTED_ATTRIBUTES, MF_BYCOMMAND);
182 #ifndef _NO_EXTENSIONS
183 case ID_PREFERED_SIZES
: {
184 calc_widths(pane
, TRUE
);
186 InvalidateRect(pane
->hWnd
, 0, TRUE
);
190 // TODO: more command ids...
197 ////////////////////////////////////////////////////////////////////////////////
199 // hSplitWnd = CreateWindow(szFrameClass, "splitter window", WS_VISIBLE|WS_CHILD,
200 // CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
201 // Globals.hMainWnd, (HMENU)SPLIT_WINDOW, hInstance, NULL);
204 // hTreeWnd = CreateTreeView(Globals.hMDIClient, "c:\\foobar.txt");
207 // hListWnd = CreateListView(Globals.hMDIClient, "");
211 ////////////////////////////////////////////////////////////////////////////////
213 static void draw_splitbar(HWND hWnd
, int x
)
216 HDC hdc
= GetDC(hWnd
);
218 GetClientRect(hWnd
, &rt
);
219 rt
.left
= x
- SPLIT_WIDTH
/2;
220 rt
.right
= x
+ SPLIT_WIDTH
/2+1;
221 InvertRect(hdc
, &rt
);
222 ReleaseDC(hWnd
, hdc
);
226 static void OnPaint(HWND hWnd
, ChildWnd
* pChildWnd
)
232 BeginPaint(hWnd
, &ps
);
233 GetClientRect(hWnd
, &rt
);
234 lastBrush
= SelectObject(ps
.hdc
, (HBRUSH
)GetStockObject(COLOR_SPLITBAR
));
235 Rectangle(ps
.hdc
, rt
.left
, rt
.top
-1, rt
.right
, rt
.bottom
+1);
236 SelectObject(ps
.hdc
, lastBrush
);
237 // rt.top = rt.bottom - GetSystemMetrics(SM_CYHSCROLL);
238 // FillRect(ps.hdc, &rt, GetStockObject(BLACK_BRUSH));
242 static void OnPaint(HWND hWnd
, ChildWnd
* pChildWnd
)
248 GetClientRect(hWnd
, &rt
);
249 BeginPaint(hWnd
, &ps
);
251 lastBrush
= SelectObject(ps
.hdc
, (HBRUSH
)GetStockObject(WHITE_BRUSH
));
252 Rectangle(ps
.hdc
, rt
.left
, rt
.top
-1, rt
.right
, rt
.bottom
+1);
253 SelectObject(ps
.hdc
, lastBrush
);
254 rt
.top
= rt
.bottom
- GetSystemMetrics(SM_CYHSCROLL
);
255 FillRect(ps
.hdc
, &rt
, GetStockObject(BLACK_BRUSH
));
257 rt.left = pChildWnd->nSplitPos-SPLIT_WIDTH/2;
258 rt.right = pChildWnd->nSplitPos+SPLIT_WIDTH/2+1;
259 lastBrush = SelectBrush(ps.hdc, (HBRUSH)GetStockObject(COLOR_SPLITBAR));
260 Rectangle(ps.hdc, rt.left, rt.top-1, rt.right, rt.bottom+1);
261 SelectObject(ps.hdc, lastBrush);
262 #ifdef _NO_EXTENSIONS
263 rt.top = rt.bottom - GetSystemMetrics(SM_CYHSCROLL);
264 FillRect(ps.hdc, &rt, GetStockObject(BLACK_BRUSH));
271 //void ResizeWnd(ChildWnd* child, int cx, int cy);
272 static void ResizeWnd(ChildWnd
* child
, int cx
, int cy
)
274 HDWP hdwp
= BeginDeferWindowPos(4);
275 RECT rt
= {0, 0, cx
, cy
};
277 cx
= child
->nSplitPos
+ SPLIT_WIDTH
/2;
278 #ifndef _NO_EXTENSIONS
281 HD_LAYOUT hdl
= {&rt
, &wp
};
282 Header_Layout(child
->left
.hwndHeader
, &hdl
);
283 DeferWindowPos(hdwp
, child
->left
.hwndHeader
, wp
.hwndInsertAfter
,
284 wp
.x
-1, wp
.y
, child
->nSplitPos
-SPLIT_WIDTH
/2+1, wp
.cy
, wp
.flags
);
285 DeferWindowPos(hdwp
, child
->right
.hwndHeader
, wp
.hwndInsertAfter
,
286 rt
.left
+cx
+1, wp
.y
, wp
.cx
-cx
+2, wp
.cy
, wp
.flags
);
289 DeferWindowPos(hdwp
, child
->left
.hWnd
, 0, rt
.left
, rt
.top
, child
->nSplitPos
-SPLIT_WIDTH
/2-rt
.left
, rt
.bottom
-rt
.top
, SWP_NOZORDER
|SWP_NOACTIVATE
);
290 DeferWindowPos(hdwp
, child
->right
.hWnd
, 0, rt
.left
+cx
+1, rt
.top
, rt
.right
-cx
, rt
.bottom
-rt
.top
, SWP_NOZORDER
|SWP_NOACTIVATE
);
291 EndDeferWindowPos(hdwp
);
294 static void OnSize(ChildWnd
* pChildWnd
, WPARAM wParam
, LPARAM lParam
)
296 if (wParam
!= SIZE_MINIMIZED
) {
297 ResizeWnd(pChildWnd
, LOWORD(lParam
), HIWORD(lParam
));
302 // FUNCTION: ChildWndProc(HWND, unsigned, WORD, LONG)
304 // PURPOSE: Processes messages for the child windows.
306 // WM_COMMAND - process the application menu
307 // WM_PAINT - Paint the main window
308 // WM_DESTROY - post a quit message and return
311 LRESULT CALLBACK
ChildWndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
313 static int last_split
;
315 ChildWnd
* pChildWnd
= (ChildWnd
*)GetWindowLong(hWnd
, GWL_USERDATA
);
320 CreateTreeWnd(pChildWnd
->hWnd
, &pChildWnd
->left
, IDW_TREE_LEFT
, pChildWnd
->szPath
);
321 CreateListWnd(pChildWnd
->hWnd
, &pChildWnd
->right
, IDW_TREE_RIGHT
, pChildWnd
->szPath
);
322 //create_tree_window(pChildWnd->hWnd, &pChildWnd->left, IDW_TREE_LEFT, IDW_HEADER_LEFT, pChildWnd->szPath);
323 //create_list_window(pChildWnd->hWnd, &pChildWnd->right, IDW_TREE_RIGHT, IDW_HEADER_RIGHT);
328 OnPaint(hWnd
, pChildWnd
);
332 // free_child_window(pChildWnd);
333 SetWindowLong(hWnd
, GWL_USERDATA
, 0);
337 if (LOWORD(lParam
) == HTCLIENT
) {
340 ScreenToClient(hWnd
, &pt
);
341 if (pt
.x
>=pChildWnd
->nSplitPos
-SPLIT_WIDTH
/2 && pt
.x
<pChildWnd
->nSplitPos
+SPLIT_WIDTH
/2+1) {
342 SetCursor(LoadCursor(0, IDC_SIZEWE
));
348 case WM_LBUTTONDOWN
: {
350 int x
= LOWORD(lParam
);
352 GetClientRect(hWnd
, &rt
);
353 if (x
>=pChildWnd
->nSplitPos
-SPLIT_WIDTH
/2 && x
<pChildWnd
->nSplitPos
+SPLIT_WIDTH
/2+1) {
354 last_split
= pChildWnd
->nSplitPos
;
355 #ifdef _NO_EXTENSIONS
356 draw_splitbar(hWnd
, last_split
);
363 if (GetCapture() == hWnd
) {
364 #ifdef _NO_EXTENSIONS
366 int x
= LOWORD(lParam
);
367 draw_splitbar(hWnd
, last_split
);
369 GetClientRect(hWnd
, &rt
);
370 pChildWnd
->nSplitPos
= x
;
371 ResizeWnd(pChildWnd
, rt
.right
, rt
.bottom
);
377 #ifdef _NO_EXTENSIONS
378 case WM_CAPTURECHANGED
:
379 if (GetCapture()==hWnd
&& last_split
>=0)
380 draw_splitbar(hWnd
, last_split
);
385 if (wParam
== VK_ESCAPE
)
386 if (GetCapture() == hWnd
) {
388 #ifdef _NO_EXTENSIONS
389 draw_splitbar(hWnd
, last_split
);
391 pChildWnd
->nSplitPos
= last_split
;
393 GetClientRect(hWnd
, &rt
);
394 ResizeWnd(pChildWnd
, rt
.right
, rt
.bottom
);
397 SetCursor(LoadCursor(0, IDC_ARROW
));
402 if (GetCapture() == hWnd
) {
404 int x
= LOWORD(lParam
);
406 #ifdef _NO_EXTENSIONS
407 HDC hdc
= GetDC(hWnd
);
408 GetClientRect(hWnd
, &rt
);
410 rt
.left
= last_split
-SPLIT_WIDTH
/2;
411 rt
.right
= last_split
+SPLIT_WIDTH
/2+1;
412 InvertRect(hdc
, &rt
);
415 rt
.left
= x
-SPLIT_WIDTH
/2;
416 rt
.right
= x
+SPLIT_WIDTH
/2+1;
417 InvertRect(hdc
, &rt
);
419 ReleaseDC(hWnd
, hdc
);
421 GetClientRect(hWnd
, &rt
);
423 if (x
>=0 && x
<rt
.right
) {
424 pChildWnd
->nSplitPos
= x
;
425 ResizeWnd(pChildWnd
, rt
.right
, rt
.bottom
);
426 rt
.left
= x
-SPLIT_WIDTH
/2;
427 rt
.right
= x
+SPLIT_WIDTH
/2+1;
428 InvalidateRect(hWnd
, &rt
, FALSE
);
429 UpdateWindow(pChildWnd
->left
.hWnd
);
431 UpdateWindow(pChildWnd
->right
.hWnd
);
437 #ifndef _NO_EXTENSIONS
438 case WM_GETMINMAXINFO
:
439 DefMDIChildProc(hWnd
, message
, wParam
, lParam
);
441 {LPMINMAXINFO lpmmi
= (LPMINMAXINFO
)lParam
;
443 lpmmi
->ptMaxTrackSize
.x
<<= 1;//2*GetSystemMetrics(SM_CXSCREEN) / SM_CXVIRTUALSCREEN
444 lpmmi
->ptMaxTrackSize
.y
<<= 1;//2*GetSystemMetrics(SM_CYSCREEN) / SM_CYVIRTUALSCREEN
449 SetCurrentDirectory(pChildWnd
->szPath
);
450 SetFocus(pChildWnd
->nFocusPanel
? pChildWnd
->right
.hWnd
: pChildWnd
->left
.hWnd
);
455 Pane
* pane
= GetFocus()==pChildWnd
->left
.hWnd
? &pChildWnd
->left
: &pChildWnd
->right
;
457 switch(HIWORD(wParam
)) {
458 case LBN_SELCHANGE
: {
459 int idx
= ListBox_GetCurSel(pane
->hWnd
);
460 Entry
* entry
= (Entry
*) ListBox_GetItemData(pane
->hWnd
, idx
);
462 if (pane
== &pChildWnd
->left
)
463 set_curdir(pChildWnd
, entry
);
469 activate_entry(pChildWnd
, pane
);
475 case WM_DISPATCH_COMMAND
: {
476 Pane
* pane
= GetFocus()==pChildWnd
->left
.hWnd
? &pChildWnd
->left
: &pChildWnd
->right
;
478 switch(LOWORD(wParam
)) {
479 case ID_WINDOW_NEW_WINDOW
:
480 //CreateChildWindow(pChildWnd->szPath);
481 CreateChildWindow(-1);
483 // ChildWnd* new_child = alloc_child_window(pChildWnd->szPath);
484 // if (!create_child_window(new_child))
490 scan_entry(pChildWnd
, pane
->cur
);
493 activate_entry(pChildWnd
, pane
);
496 case ID_WINDOW_CASCADE
:
497 SendMessage(Globals
.hMDIClient
, WM_MDICASCADE
, 0, 0);
499 case ID_WINDOW_TILE_HORZ
:
500 SendMessage(Globals
.hMDIClient
, WM_MDITILE
, MDITILE_HORIZONTAL
, 0);
502 case ID_WINDOW_TILE_VERT
:
503 SendMessage(Globals
.hMDIClient
, WM_MDITILE
, MDITILE_VERTICAL
, 0);
505 case ID_WINDOW_ARRANGE_ICONS
:
506 SendMessage(Globals
.hMDIClient
, WM_MDIICONARRANGE
, 0, 0);
509 return pane_command(pane
, LOWORD(wParam
));
514 //#ifndef _NO_EXTENSIONS
516 int idCtrl
= (int)wParam
;
517 NMHDR
* pnmh
= (NMHDR
*)lParam
;
519 //return pane_notify(pnmh->idFrom==IDW_HEADER_LEFT? &pChildWnd->left: &pChildWnd->right, pnmh);
520 if (idCtrl
== IDW_TREE_LEFT
) {
521 SendMessage(pChildWnd
->left
.hWnd
, message
, wParam
, lParam
);
523 if (idCtrl
== IDW_TREE_RIGHT
) {
524 SendMessage(pChildWnd
->right
.hWnd
, message
, wParam
, lParam
);
531 if (wParam
!= SIZE_MINIMIZED
) {
532 OnSize(pChildWnd
, wParam
, lParam
);
536 return DefMDIChildProc(hWnd
, message
, wParam
, lParam
);
542 RegenerateUserEnvironment
544 ATOM
RegisterChildWnd(HINSTANCE hInstance
, int res_id
)
546 WNDCLASSEX wcFrame
= {
548 CS_HREDRAW
| CS_VREDRAW
/*style*/,
553 LoadIcon(hInstance
, MAKEINTRESOURCE(IDI_WINFILE
)),
554 LoadCursor(0, IDC_ARROW
),
558 (HICON
)LoadImage(hInstance
, MAKEINTRESOURCE(IDI_WINFILE
), IMAGE_ICON
,
559 GetSystemMetrics(SM_CXSMICON
), GetSystemMetrics(SM_CYSMICON
), LR_SHARED
)
561 ATOM hFrameWndClass
= RegisterClassEx(&wcFrame
); // register frame window class
562 return hFrameWndClass
;