[ROSAPPS]
[reactos.git] / rosapps / applications / imagesoft / mainwnd.c
1 #include <precomp.h>
2
3 static const TCHAR szMainWndClass[] = TEXT("ImageSoftWndClass");
4
5 #define ID_MDI_FIRSTCHILD 50000
6 #define ID_MDI_WINDOWMENU 5
7 #define NUM_FLT_WND 3
8
9 /* toolbar buttons */
10 TBBUTTON StdButtons[] = {
11 /* iBitmap, idCommand, fsState, fsStyle, bReserved[2], dwData, iString */
12 {TBICON_NEW, ID_NEW, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0}, /* new */
13 {TBICON_OPEN, ID_OPEN, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0}, /* open */
14 {TBICON_SAVE, ID_SAVE, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0}, /* save */
15
16 {10, 0, TBSTATE_ENABLED, BTNS_SEP, {0}, 0, 0}, /* separator */
17
18 {TBICON_PRINT, ID_PRINTPRE, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0 }, /* print */
19 {TBICON_PRINTPRE, ID_PRINT, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0 }, /* print preview */
20
21 {10, 0, TBSTATE_ENABLED, BTNS_SEP, {0}, 0, 0}, /* separator */
22
23 {TBICON_CUT, ID_CUT, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0 }, /* cut */
24 {TBICON_COPY, ID_COPY, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0 }, /* copy */
25 {TBICON_PASTE, ID_PASTE, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0 }, /* paste */
26
27 {10, 0, TBSTATE_ENABLED, BTNS_SEP, {0}, 0, 0}, /* separator */
28
29 {TBICON_UNDO, ID_UNDO, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0 }, /* undo */
30 {TBICON_REDO, ID_REDO, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0 }, /* redo */
31
32 {10, 0, TBSTATE_ENABLED, BTNS_SEP, {0}, 0, 0},
33 };
34
35 TBBUTTON TextButtons[] = {
36 {10, 0, TBSTATE_ENABLED, BTNS_SEP, {0}, 0, 0}, /* separator */
37
38 {TBICON_BOLD, ID_BOLD, TBSTATE_ENABLED, BTNS_BUTTON | TBSTYLE_CHECK, {0}, 0, 0}, /* bold */
39 {TBICON_ITALIC, ID_ITALIC, TBSTATE_ENABLED, BTNS_BUTTON | TBSTYLE_CHECK, {0}, 0, 0}, /* italic */
40 {TBICON_ULINE, ID_ULINE, TBSTATE_ENABLED, BTNS_BUTTON | TBSTYLE_CHECK, {0}, 0, 0}, /* underline */
41
42 {10, 0, TBSTATE_ENABLED, BTNS_SEP, {0}, 0, 0}, /* separator */
43
44 {TBICON_TXTLEFT, ID_TXTLEFT, TBSTATE_ENABLED | TBSTATE_CHECKED, BTNS_BUTTON | TBSTYLE_GROUP | TBSTYLE_CHECK, {0}, 0, 0 }, /* left justified */
45 {TBICON_TXTCENTER,ID_TXTCENTER,TBSTATE_ENABLED, BTNS_BUTTON | TBSTYLE_GROUP | TBSTYLE_CHECK, {0}, 0, 0 }, /* centered */
46 {TBICON_TXTRIGHT, ID_TXTRIGHT, TBSTATE_ENABLED, BTNS_BUTTON | TBSTYLE_GROUP | TBSTYLE_CHECK, {0}, 0, 0 }, /* right justified */
47
48 {10, 0, TBSTATE_ENABLED, BTNS_SEP, {0}, 0, 0}, /* separator */
49 };
50
51
52
53 /* menu hints */
54 static const MENU_HINT MainMenuHintTable[] = {
55 /* File Menu */
56 {ID_BLANK, IDS_HINT_BLANK},
57 {ID_NEW, IDS_HINT_NEW},
58 {ID_OPEN, IDS_HINT_OPEN},
59 {ID_CLOSE, IDS_HINT_CLOSE},
60 {ID_CLOSEALL, IDS_HINT_CLOSEALL},
61 {ID_SAVE, IDS_HINT_SAVE},
62 {ID_SAVEAS, IDS_HINT_SAVEAS},
63 {ID_PRINTPRE, IDS_HINT_PRINTPRE},
64 {ID_PRINT, IDS_HINT_PRINT},
65 {ID_PROP, IDS_HINT_PROP},
66 {ID_EXIT, IDS_HINT_EXIT},
67
68 /* view menu */
69 {ID_TOOLS, IDS_HINT_TOOLS},
70 {ID_COLOR, IDS_HINT_COLORS},
71 {ID_HISTORY, IDS_HINT_HISTORY},
72 {ID_STATUSBAR, IDS_HINT_STATUS},
73
74 /* Window Menu */
75 {ID_WINDOW_NEXT, IDS_HINT_NEXT},
76 {ID_WINDOW_CASCADE, IDS_HINT_CASCADE},
77 {ID_WINDOW_TILE_HORZ, IDS_HINT_TILE_HORZ},
78 {ID_WINDOW_TILE_VERT, IDS_HINT_TILE_VERT},
79 {ID_WINDOW_ARRANGE, IDS_HINT_ARRANGE}
80 };
81
82 static const MENU_HINT SystemMenuHintTable[] = {
83 {SC_RESTORE, IDS_HINT_SYS_RESTORE},
84 {SC_MOVE, IDS_HINT_SYS_MOVE},
85 {SC_SIZE, IDS_HINT_SYS_SIZE},
86 {SC_MINIMIZE, IDS_HINT_SYS_MINIMIZE},
87 {SC_MAXIMIZE, IDS_HINT_SYS_MAXIMIZE},
88 {SC_CLOSE, IDS_HINT_CLOSE},
89 {SC_NEXTWINDOW, IDS_HINT_NEXT},
90 };
91
92
93 /* Toolbars */
94 #define ID_TOOLBAR_STANDARD 0
95 #define ID_TOOLBAR_TEXT 1
96 static const TCHAR szToolbarStandard[] = TEXT("STANDARD");
97 static const TCHAR szToolbarText[] = TEXT("TEXT");
98
99
100 /* Test Toolbar */
101 #define ID_TOOLBAR_TEST 5
102 static const TCHAR szToolbarTest[] = TEXT("TEST");
103
104 /* Toolbars table */
105 static const DOCKBAR MainDockBars[] = {
106 {ID_TOOLBAR_STANDARD, szToolbarStandard, IDS_TOOLBAR_STANDARD, TOP_DOCK},
107 {ID_TOOLBAR_TEST, szToolbarTest, IDS_TOOLBAR_TEST, TOP_DOCK},
108 {ID_TOOLBAR_TEXT, szToolbarText, IDS_TOOLBAR_TEXT, TOP_DOCK},
109 };
110
111
112 static BOOL CALLBACK
113 MainWndCreateToolbarClient(struct _TOOLBAR_DOCKS *TbDocks,
114 const DOCKBAR *Dockbar,
115 PVOID Context,
116 HWND hParent,
117 HWND *hwnd)
118 {
119 const TBBUTTON *Buttons = NULL;
120 UINT NumButtons = 0;
121 UINT StartImageRes = 0;
122 HWND hWndClient = NULL;
123
124 UNREFERENCED_PARAMETER(Context);
125
126 switch (Dockbar->BarId)
127 {
128 case ID_TOOLBAR_STANDARD:
129 {
130 Buttons = StdButtons;
131 NumButtons = sizeof(StdButtons) / sizeof(StdButtons[0]);
132 StartImageRes = IDB_MAINNEWICON;
133 break;
134 }
135
136 case ID_TOOLBAR_TEXT:
137 {
138 Buttons = TextButtons;
139 NumButtons = sizeof(TextButtons) / sizeof(TextButtons[0]);
140 StartImageRes = IDB_TEXTBOLD;
141 break;
142 }
143
144 case ID_TOOLBAR_TEST:
145 {/*
146 hWndClient = CreateWindowEx(WS_EX_TOOLWINDOW,
147 TEXT("BUTTON"),
148 TEXT("Test Button"),
149 WS_CHILD | WS_VISIBLE,
150 0,
151 0,
152 150,
153 25,
154 hParent,
155 NULL,
156 hInstance,
157 NULL);*/
158 break;
159 }
160 }
161
162 if (Buttons != NULL)
163 {
164 hWndClient = CreateWindowEx(0,
165 TOOLBARCLASSNAME,
166 NULL,
167 WS_CHILD | WS_CLIPSIBLINGS |
168 CCS_NOPARENTALIGN | CCS_NOMOVEY | CCS_NORESIZE | CCS_NODIVIDER |
169 TBSTYLE_FLAT | TBSTYLE_TOOLTIPS,
170 0,
171 0,
172 0,
173 0,
174 hParent,
175 NULL,
176 hInstance,
177 NULL);
178 if (hWndClient != NULL)
179 {
180 HIMAGELIST hImageList;
181
182 SendMessage(hWndClient,
183 TB_SETEXTENDEDSTYLE,
184 0,
185 TBSTYLE_EX_HIDECLIPPEDBUTTONS);
186
187 SendMessage(hWndClient,
188 TB_BUTTONSTRUCTSIZE,
189 sizeof(Buttons[0]),
190 0);
191
192 SendMessage(hWndClient,
193 TB_SETBITMAPSIZE,
194 0,
195 (LPARAM)MAKELONG(TB_BMP_WIDTH, TB_BMP_HEIGHT));
196
197 hImageList = InitImageList(NumButtons,
198 StartImageRes);
199
200 ImageList_Destroy((HIMAGELIST)SendMessage(hWndClient,
201 TB_SETIMAGELIST,
202 0,
203 (LPARAM)hImageList));
204
205 SendMessage(hWndClient,
206 TB_ADDBUTTONS,
207 NumButtons,
208 (LPARAM)Buttons);
209
210 }
211 }
212
213 switch (Dockbar->BarId)
214 {
215 case ID_TOOLBAR_TEXT:
216 {
217 HWND hFontType;
218 HWND hFontSize;
219
220 /* font selection combo */
221 hFontType = CreateWindowEx(0,
222 WC_COMBOBOX,
223 NULL,
224 WS_CHILD | WS_VISIBLE | WS_VSCROLL |
225 CBS_DROPDOWN | CBS_SORT | CBS_HASSTRINGS, //| CBS_OWNERDRAWFIXED,
226 0, 0, 120, 0,
227 hParent,
228 NULL,
229 hInstance,
230 NULL);
231
232 if (hFontType != NULL)
233 {
234 MakeFlatCombo(hFontType);
235
236 SetParent(hFontType,
237 hWndClient);
238
239 if (!ToolbarInsertSpaceForControl(hWndClient,
240 hFontType,
241 0,
242 ID_TXTFONTNAME,
243 TRUE))
244 {
245 DestroyWindow(hFontType);
246 }
247
248 /* Create the list of fonts */
249 FillFontStyleComboList(hFontType);
250 }
251
252 /* font size combo */
253 hFontSize = CreateWindowEx(0,
254 WC_COMBOBOX,
255 NULL,
256 WS_CHILD | WS_VISIBLE | CBS_DROPDOWN,
257 0, 0, 50, 0,
258 hParent,
259 NULL,
260 hInstance,
261 NULL);
262 if (hFontSize != NULL)
263 {
264 MakeFlatCombo(hFontSize);
265
266 SetParent(hFontSize,
267 hWndClient);
268
269 if (!ToolbarInsertSpaceForControl(hWndClient,
270 hFontSize,
271 1,
272 ID_TXTFONTSIZE,
273 TRUE))
274 {
275 DestroyWindow(hFontSize);
276 }
277
278 /* Update the font-size-list */
279 FillFontSizeComboList(hFontSize);
280 }
281 break;
282 }
283 }
284
285 if (hWndClient != NULL)
286 {
287 *hwnd = hWndClient;
288 return TRUE;
289 }
290
291 return FALSE;
292 }
293
294 static BOOL CALLBACK
295 MainWndDestroyToolbarClient(struct _TOOLBAR_DOCKS *TbDocks,
296 const DOCKBAR *Dockbar,
297 PVOID Context,
298 HWND hwnd)
299 {
300 UNREFERENCED_PARAMETER(TbDocks);
301 UNREFERENCED_PARAMETER(Dockbar);
302 UNREFERENCED_PARAMETER(Context);
303
304 DestroyWindow(hwnd);
305 return TRUE;
306 }
307
308 static BOOL CALLBACK
309 MainWndToolbarInsertBand(struct _TOOLBAR_DOCKS *TbDocks,
310 const DOCKBAR *Dockbar,
311 PVOID Context,
312 UINT *Index,
313 LPREBARBANDINFO rbi)
314 {
315 switch (rbi->wID)
316 {
317 case ID_TOOLBAR_TEXT:
318 case ID_TOOLBAR_STANDARD:
319 {
320 SIZE Size;
321
322 if (SendMessage(rbi->hwndChild,
323 TB_GETMAXSIZE,
324 0,
325 (LPARAM)&Size))
326 {
327 rbi->fStyle |= RBBS_USECHEVRON | RBBS_HIDETITLE;
328 rbi->fMask |= RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_IDEALSIZE;
329 rbi->cx = rbi->cxIdeal = Size.cx;
330 rbi->cxMinChild = 0;
331 rbi->cyMinChild = Size.cy;
332 }
333 break;
334 }
335
336 case ID_TOOLBAR_TEST:
337 {
338 RECT rcBtn;
339
340 if (GetWindowRect(rbi->hwndChild,
341 &rcBtn))
342 {
343 rbi->fStyle |= RBBS_HIDETITLE;
344 rbi->fMask |= RBBIM_SIZE | RBBIM_CHILDSIZE;
345 rbi->cx = rcBtn.right - rcBtn.left;
346 rbi->cxMinChild = 0;
347 rbi->cyMinChild = rcBtn.bottom - rcBtn.top;
348 }
349 break;
350 }
351 }
352 return TRUE;
353 }
354
355 static VOID
356 TbCustomControlChange(HWND hWndToolbar,
357 HWND hWndControl,
358 BOOL Vert)
359 {
360 /* the toolbar changed from horizontal to vertical or vice versa... */
361 return;
362 }
363
364 static VOID CALLBACK
365 MainWndToolbarDockBand(struct _TOOLBAR_DOCKS *TbDocks,
366 const DOCKBAR *Dockbar,
367 PVOID Context,
368 DOCK_POSITION DockFrom,
369 DOCK_POSITION DockTo,
370 LPREBARBANDINFO rbi)
371 {
372 if (rbi->fMask & RBBIM_CHILD && rbi->hwndChild != NULL)
373 {
374 switch (rbi->wID)
375 {
376 case ID_TOOLBAR_TEXT:
377 case ID_TOOLBAR_STANDARD:
378 {
379 SIZE Size;
380 BOOL Vert;
381 DWORD dwStyle = (DWORD)SendMessage(rbi->hwndChild,
382 TB_GETSTYLE,
383 0,
384 0);
385 switch (DockTo)
386 {
387 case LEFT_DOCK:
388 case RIGHT_DOCK:
389 dwStyle |= CCS_VERT | TBSTYLE_WRAPABLE;
390 Vert = TRUE;
391 break;
392
393 default:
394 dwStyle &= ~(CCS_VERT | TBSTYLE_WRAPABLE);
395 Vert = FALSE;
396 break;
397 }
398
399 SendMessage(rbi->hwndChild,
400 TB_SETSTYLE,
401 0,
402 (LPARAM)dwStyle);
403
404 ToolbarUpdateControlSpaces(rbi->hwndChild,
405 TbCustomControlChange);
406
407 if (SendMessage(rbi->hwndChild,
408 TB_GETMAXSIZE,
409 0,
410 (LPARAM)&Size))
411 {
412 rbi->fMask |= RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_IDEALSIZE;
413 rbi->cx = rbi->cxIdeal = (Vert ? Size.cy : Size.cx);
414 rbi->cxMinChild = 0;
415 rbi->cyMinChild = (Vert ? Size.cx : Size.cy);
416 }
417 break;
418 }
419
420 case ID_TOOLBAR_TEST:
421 {
422 if (DockTo == NO_DOCK)
423 {
424 rbi->fMask |= RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_IDEALSIZE;
425 rbi->cx = rbi->cxIdeal = 150;
426 rbi->cxMinChild = 0;
427 rbi->cyMinChild = 40;
428 }
429 break;
430 }
431 }
432 }
433 }
434
435 static VOID CALLBACK
436 MainWndToolbarChevronPushed(struct _TOOLBAR_DOCKS *TbDocks,
437 const DOCKBAR *Dockbar,
438 PVOID Context,
439 HWND hwndChild,
440 LPNMREBARCHEVRON lpnm)
441 {
442 switch (lpnm->wID)
443 {
444 case ID_TOOLBAR_STANDARD:
445 {
446 MapWindowPoints(lpnm->hdr.hwndFrom,
447 HWND_DESKTOP,
448 (LPPOINT)&lpnm->rc,
449 2);
450 /* Create a popup menu for all toolbar icons hidden */
451 break;
452 }
453 }
454 }
455
456 static VOID
457 MainWndMoveFloatingWindows(PMAIN_WND_INFO Info,
458 PRECT wndOldPos)
459 {
460 RECT wndNewPos, TbRect;
461 INT i, xMoved, yMoved;
462 PFLT_WND WndArr[NUM_FLT_WND];
463
464 if (GetWindowRect(Info->hSelf,
465 &wndNewPos))
466 {
467
468 xMoved = wndNewPos.left - wndOldPos->left;
469 yMoved = wndNewPos.top - wndOldPos->top;
470
471 /* store the pointers in an array */
472 WndArr[0] = Info->fltTools;
473 WndArr[1] = Info->fltColors;
474 WndArr[2] = Info->fltHistory;
475
476 for (i = 0; i < NUM_FLT_WND; i++)
477 {
478 GetWindowRect(WndArr[i]->hSelf,
479 &TbRect);
480
481 WndArr[i]->x = TbRect.left + xMoved;
482 WndArr[i]->y = TbRect.top + yMoved;
483
484 MoveWindow(WndArr[i]->hSelf,
485 WndArr[i]->x,
486 WndArr[i]->y,
487 WndArr[i]->Width,
488 WndArr[i]->Height,
489 TRUE);
490 }
491
492 CopyMemory(wndOldPos,
493 &wndNewPos,
494 sizeof(RECT));
495 }
496 }
497
498
499 static VOID
500 MainWndResetFloatingWindows(PMAIN_WND_INFO Info)
501 {
502 RECT rect;
503
504 if (GetWindowRect(Info->hMdiClient,
505 &rect))
506 {
507
508 /* tools datum */
509 MoveWindow(Info->fltTools->hSelf,
510 rect.left + 5,
511 rect.top + 5,
512 Info->fltTools->Width,
513 Info->fltTools->Height,
514 TRUE);
515
516 /* colors datum */
517 MoveWindow(Info->fltColors->hSelf,
518 rect.left + 5,
519 rect.bottom - Info->fltColors->Height - 5,
520 Info->fltColors->Width,
521 Info->fltColors->Height,
522 TRUE);
523
524 /* history datum */
525 MoveWindow(Info->fltHistory->hSelf,
526 rect.right - Info->fltHistory->Width - 5,
527 rect.top + 5,
528 Info->fltHistory->Width,
529 Info->fltHistory->Height,
530 TRUE);
531 }
532 }
533
534 static VOID
535 MainWndCreateFloatWindows(PMAIN_WND_INFO Info)
536 {
537 RECT rect;
538 HMENU hMenu;
539 UINT Res;
540 PFLT_WND WndArr[NUM_FLT_WND]; /* temp array for looping */
541 INT i;
542
543 Info->fltTools = HeapAlloc(ProcessHeap,
544 HEAP_ZERO_MEMORY,
545 sizeof(FLT_WND));
546 Info->fltColors = HeapAlloc(ProcessHeap,
547 HEAP_ZERO_MEMORY,
548 sizeof(FLT_WND));
549 Info->fltHistory = HeapAlloc(ProcessHeap,
550 HEAP_ZERO_MEMORY,
551 sizeof(FLT_WND));
552
553 /* set window dimensions */
554 Info->fltTools->Width = 53;
555 Info->fltTools->Height = 300;
556 Info->fltColors->Width = 200;
557 Info->fltColors->Height = 200;
558 Info->fltHistory->Width = 150;
559 Info->fltHistory->Height = 150;
560
561 if (! GetWindowRect(Info->hMdiClient,
562 &rect))
563 {
564 return;
565 }
566
567 /* Set window datums */
568 Info->fltTools->x = rect.left + 5;
569 Info->fltTools->y = rect.top + 5;
570
571 Info->fltColors->x = rect.left + 5;
572 Info->fltColors->y = rect.bottom - Info->fltColors->Height - 5;
573
574 Info->fltHistory->x = rect.right - Info->fltHistory->Width - 5;
575 Info->fltHistory->y = rect.top + 5;
576
577 /* save pointers into array incrementing within the loop*/
578 WndArr[0] = Info->fltTools;
579 WndArr[1] = Info->fltColors;
580 WndArr[2] = Info->fltHistory;
581
582 for (i = 0, Res = IDS_FLT_TOOLS; Res < IDS_FLT_TOOLS + NUM_FLT_WND; Res++, i++)
583 {
584 if (! AllocAndLoadString(&WndArr[i]->lpName,
585 hInstance,
586 Res))
587 {
588 WndArr[i]->lpName = NULL;
589 }
590
591 WndArr[i]->hSelf = CreateWindowEx(WS_EX_TOOLWINDOW,
592 TEXT("ImageSoftFloatWndClass"),
593 WndArr[i]->lpName,
594 WS_POPUPWINDOW | WS_DLGFRAME | WS_VISIBLE,
595 WndArr[i]->x,
596 WndArr[i]->y,
597 WndArr[i]->Width,
598 WndArr[i]->Height,
599 Info->hSelf,
600 NULL,
601 hInstance,
602 WndArr[i]);
603 ShowWindow(WndArr[i]->hSelf, SW_HIDE);
604 }
605
606 hMenu = GetMenu(Info->hSelf);
607
608 if (Info->fltTools->hSelf != NULL)
609 {
610 if (FloatToolbarCreateToolsGui(Info))
611 {
612 CheckMenuItem(hMenu,
613 ID_TOOLS,
614 MF_CHECKED);
615
616 ShowHideWindow(Info->fltTools->hSelf);
617 }
618 }
619
620 if (Info->fltColors->hSelf != NULL)
621 {
622 if (FloatToolbarCreateColorsGui(Info))
623 {
624
625 }
626 }
627
628 if (Info->fltHistory->hSelf != NULL)
629 {
630 if (FloatToolbarCreateHistoryGui(Info))
631 {
632
633 }
634 }
635
636 }
637
638 static VOID
639 MainWndDestroyFloatWindows(PMAIN_WND_INFO Info)
640 {
641 if (Info->fltTools != NULL)
642 HeapFree(ProcessHeap, 0, Info->fltTools);
643
644 if (Info->fltColors != NULL)
645 HeapFree(ProcessHeap, 0, Info->fltColors);
646
647 if (Info->fltHistory != NULL)
648 HeapFree(ProcessHeap, 0, Info->fltHistory);
649 }
650
651
652
653 static const DOCKBAR_ITEM_CALLBACKS MainWndDockBarCallbacks = {
654 MainWndCreateToolbarClient,
655 MainWndDestroyToolbarClient,
656 MainWndToolbarInsertBand,
657 MainWndToolbarDockBand,
658 MainWndToolbarChevronPushed,
659 };
660
661 static VOID
662 CreateToolbars(PMAIN_WND_INFO Info)
663 {
664 UINT i;
665
666 for (i = 0; i < sizeof(MainDockBars) / sizeof(MainDockBars[0]); i++)
667 {
668 /* FIXME - lookup whether to display the toolbar */
669 TbdAddToolbar(&Info->ToolDocks,
670 &MainDockBars[i],
671 Info,
672 &MainWndDockBarCallbacks);
673 }
674
675 MainWndCreateFloatWindows(Info);
676 }
677
678 static VOID CALLBACK
679 MainWndResize(PVOID Context,
680 LONG cx,
681 LONG cy)
682 {
683 RECT rcClient = {0};
684 RECT rcStatus = {0};
685 HDWP dwp;
686 INT DocksVisible;
687 PMAIN_WND_INFO Info = (PMAIN_WND_INFO)Context;
688
689 /* Calculate the MDI client rectangle */
690 rcClient.right = cx;
691 rcClient.bottom = cy;
692
693 if (Info->hStatus != NULL)
694 {
695 GetWindowRect(Info->hStatus,
696 &rcStatus);
697 rcClient.bottom -= (rcStatus.bottom - rcStatus.top);
698 }
699
700 /* Adjust the client rect if docked toolbars are visible */
701 DocksVisible = TbdAdjustUpdateClientRect(&Info->ToolDocks,
702 &rcClient);
703
704 dwp = BeginDeferWindowPos(2 + DocksVisible);
705 if (dwp != NULL)
706 {
707 /* Update the toolbar docks */
708 if (DocksVisible != 0)
709 {
710 dwp = TbdDeferDocks(dwp,
711 &Info->ToolDocks);
712 if (dwp == NULL)
713 return;
714 }
715
716 /* Update the MDI client */
717 if (Info->hMdiClient != NULL)
718 {
719 dwp = DeferWindowPos(dwp,
720 Info->hMdiClient,
721 NULL,
722 rcClient.left,
723 rcClient.top,
724 rcClient.right - rcClient.left,
725 rcClient.bottom - rcClient.top,
726 SWP_NOZORDER);
727 if (dwp == NULL)
728 return;
729 }
730
731 /* Update the status bar */
732 if (Info->hStatus != NULL)
733 {
734 dwp = DeferWindowPos(dwp,
735 Info->hStatus,
736 NULL,
737 0,
738 cy - (rcStatus.bottom - rcStatus.top),
739 cx,
740 rcStatus.bottom - rcStatus.top,
741 SWP_NOZORDER);
742 if (dwp == NULL)
743 return;
744 }
745
746 EndDeferWindowPos(dwp);
747 }
748 }
749
750 static VOID
751 InitMainWnd(PMAIN_WND_INFO Info)
752 {
753 CLIENTCREATESTRUCT ccs;
754 INT statwidths[] = {110, -1};
755
756 /* FIXME - create controls and initialize the application */
757
758 /* create the status bar */
759 Info->hStatus = CreateWindowEx(0,
760 STATUSCLASSNAME,
761 NULL,
762 WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | CCS_NOPARENTALIGN | SBARS_SIZEGRIP,
763 0,
764 0,
765 0,
766 0,
767 Info->hSelf,
768 (HMENU)IDC_STATUSBAR,
769 hInstance,
770 NULL);
771
772 if (Info->hStatus != NULL)
773 SendMessage(Info->hStatus,
774 SB_SETPARTS,
775 sizeof(statwidths)/sizeof(int),
776 (LPARAM)statwidths);
777
778 /* create the MDI client window */
779 ccs.hWindowMenu = GetSubMenu(GetMenu(Info->hSelf),
780 ID_MDI_WINDOWMENU);
781 ccs.idFirstChild = ID_MDI_FIRSTCHILD;
782 Info->hMdiClient = CreateWindowEx(WS_EX_ACCEPTFILES | WS_EX_CLIENTEDGE,
783 TEXT("MDICLIENT"),
784 NULL,
785 WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VSCROLL | WS_HSCROLL,
786 0,
787 0,
788 0,
789 0,
790 Info->hSelf,
791 NULL,
792 hInstance,
793 &ccs);
794
795 TbdInitializeDocks(&Info->ToolDocks,
796 Info->hSelf,
797 Info,
798 MainWndResize);
799
800 CreateToolbars(Info);
801
802 /* initialize file open/save structure */
803 FileInitialize(Info->hSelf);
804 }
805
806 static VOID
807 MainWndCommand(PMAIN_WND_INFO Info,
808 WORD CmdId,
809 HWND hControl)
810 {
811 static TCHAR szFileName[MAX_PATH];
812 static TCHAR szImageName[MAX_PATH];
813
814 UNREFERENCED_PARAMETER(hControl);
815
816 switch (CmdId)
817 {
818 case ID_NEW:
819 {
820 MessageBox(NULL, _T("Not yet implemented"), NULL, 0);
821 }
822 break;
823
824 case ID_OPEN:
825 {
826 OPEN_IMAGE_EDIT_INFO OpenInfo;
827
828 if (DoOpenFile(Info->hSelf,
829 szFileName, /* full file path */
830 szImageName)) /* file name */
831 {
832 OpenInfo.CreateNew = FALSE;
833
834 OpenInfo.Open.lpImagePath = szFileName;
835 OpenInfo.lpImageName = szImageName;
836
837 CreateImageEditWindow(Info,
838 &OpenInfo);
839
840 /* FIXME: move flt wnd's if scroll bars show
841 MainWndResetFloatingWindows(Info->hMdiClient); */
842 }
843
844 }
845 break;
846
847 case ID_TOOLS:
848 {
849 HMENU hMenu = GetMenu(Info->hSelf);
850
851 if (hMenu != NULL)
852 {
853 UINT uCheck = MF_CHECKED;
854
855 if (ShowHideWindow(Info->fltTools->hSelf))
856 uCheck = MF_UNCHECKED;
857
858 CheckMenuItem(hMenu,
859 ID_TOOLS,
860 uCheck);
861 }
862 }
863 break;
864
865 case ID_COLOR:
866 {
867 HMENU hMenu = GetMenu(Info->hSelf);
868
869 if (hMenu != NULL)
870 {
871 UINT uCheck = MF_CHECKED;
872
873 if (ShowHideWindow(Info->fltColors->hSelf))
874 uCheck = MF_UNCHECKED;
875
876 CheckMenuItem(hMenu,
877 ID_COLOR,
878 uCheck);
879 }
880 }
881 break;
882
883 case ID_HISTORY:
884 {
885 HMENU hMenu = GetMenu(Info->hSelf);
886
887 if (hMenu != NULL)
888 {
889 UINT uCheck = MF_CHECKED;
890
891 if (ShowHideWindow(Info->fltHistory->hSelf))
892 uCheck = MF_UNCHECKED;
893
894 CheckMenuItem(hMenu,
895 ID_HISTORY,
896 uCheck);
897 }
898 }
899 break;
900
901 case ID_BRIGHTNESS:
902 DialogBoxParam(hInstance,
903 MAKEINTRESOURCE(IDD_BRIGHTNESS),
904 Info->hSelf,
905 BrightnessProc,
906 (LPARAM)Info);
907 break;
908
909 case ID_CONTRAST:
910 /* FIXME : Create a window for contrast */
911 break;
912
913 case ID_BLACKANDWHITE:
914 {
915 if (Info->ImageEditors)
916 {
917 DisplayBlackAndWhite(Info->ImageEditors->hSelf,
918 Info->ImageEditors->hDCMem,
919 Info->ImageEditors->hBitmap);
920 }
921 }
922 break;
923
924 case ID_INVERTCOLORS:
925 {
926 if (Info->ImageEditors)
927 {
928 DisplayInvertedColors(Info->ImageEditors->hSelf,
929 Info->ImageEditors->hDCMem,
930 Info->ImageEditors->hBitmap);
931 }
932 }
933 break;
934
935 case ID_BLUR:
936 {
937 if (Info->ImageEditors)
938 {
939 DisplayBlur(Info->ImageEditors->hSelf,
940 Info->ImageEditors->hDCMem,
941 Info->ImageEditors->hBitmap);
942 }
943 }
944 break;
945
946 case ID_SHARPEN:
947 {
948 if (Info->ImageEditors)
949 {
950 DisplaySharpness(Info->ImageEditors->hSelf,
951 Info->ImageEditors->hDCMem,
952 Info->ImageEditors->hBitmap);
953 }
954 }
955 break;
956
957 case ID_EXIT:
958 SendMessage(Info->hSelf,
959 WM_CLOSE,
960 0,
961 0);
962 break;
963
964 /* Window Menu */
965 case ID_WINDOW_TILE_HORZ:
966 SendMessage(Info->hMdiClient,
967 WM_MDITILE,
968 MDITILE_HORIZONTAL,
969 0);
970 break;
971
972 case ID_WINDOW_TILE_VERT:
973 SendMessage(Info->hMdiClient,
974 WM_MDITILE,
975 MDITILE_VERTICAL,
976 0);
977 break;
978
979 case ID_WINDOW_CASCADE:
980 SendMessage(Info->hMdiClient,
981 WM_MDICASCADE,
982 0,
983 0);
984 break;
985
986 case ID_WINDOW_ARRANGE:
987 SendMessage(Info->hMdiClient,
988 WM_MDIICONARRANGE,
989 0,
990 0);
991 break;
992
993 case ID_WINDOW_NEXT:
994 SendMessage(Info->hMdiClient,
995 WM_MDINEXT,
996 0,
997 0);
998 break;
999
1000 /* Help Menu */
1001 case ID_ABOUT:
1002 DialogBox(hInstance,
1003 MAKEINTRESOURCE(IDD_ABOUTBOX),
1004 Info->hSelf,
1005 AboutDialogProc);
1006 break;
1007 }
1008 }
1009
1010 static VOID
1011 DestroyMainWnd(PMAIN_WND_INFO Info)
1012 {
1013 /* FIXME - cleanup allocated resources */
1014
1015 MainWndDestroyFloatWindows(Info);
1016 }
1017
1018
1019 static VOID
1020 UpdateMainStatusBar(PMAIN_WND_INFO Info)
1021 {
1022 if (Info->hStatus != NULL)
1023 {
1024 SendMessage(Info->hStatus,
1025 SB_SIMPLE,
1026 (WPARAM)Info->InMenuLoop,
1027 0);
1028 }
1029 }
1030
1031 static BOOL
1032 MainWndMenuHint(PMAIN_WND_INFO Info,
1033 WORD CmdId,
1034 const MENU_HINT *HintArray,
1035 DWORD HintsCount,
1036 UINT DefHintId)
1037 {
1038 BOOL Found = FALSE;
1039 const MENU_HINT *LastHint;
1040 UINT HintId = DefHintId;
1041
1042 LastHint = HintArray + HintsCount;
1043 while (HintArray != LastHint)
1044 {
1045 if (HintArray->CmdId == CmdId)
1046 {
1047 HintId = HintArray->HintId;
1048 Found = TRUE;
1049 break;
1050 }
1051 HintArray++;
1052 }
1053
1054 StatusBarLoadString(Info->hStatus,
1055 SB_SIMPLEID,
1056 hInstance,
1057 HintId);
1058
1059 return Found;
1060 }
1061
1062 static LRESULT CALLBACK
1063 MainWndProc(HWND hwnd,
1064 UINT uMsg,
1065 WPARAM wParam,
1066 LPARAM lParam)
1067 {
1068 PMAIN_WND_INFO Info;
1069 LRESULT Ret = 0;
1070 static BOOL bLBMouseDown = FALSE;
1071 static RECT wndOldPos;
1072
1073 /* Get the window context */
1074 Info = (PMAIN_WND_INFO)GetWindowLongPtr(hwnd,
1075 GWLP_USERDATA);
1076 if (Info == NULL && uMsg != WM_CREATE)
1077 {
1078 goto HandleDefaultMessage;
1079 }
1080
1081 switch (uMsg)
1082 {
1083 case WM_SIZE:
1084 {
1085 MainWndResize(Info,
1086 LOWORD(lParam),
1087 HIWORD(lParam));
1088 /* NOTE - do *not* forward this message to DefFrameProc! Otherwise the MDI client
1089 will attempt to resize itself */
1090
1091 /* reposition the floating toolbars */
1092 if ((wParam == SIZE_MAXIMIZED) || (wParam == SIZE_RESTORED))
1093 MainWndResetFloatingWindows(Info);
1094
1095 break;
1096 }
1097
1098 case WM_NCLBUTTONDOWN:
1099 bLBMouseDown = TRUE;
1100 DefWindowProc(hwnd,
1101 uMsg,
1102 wParam,
1103 lParam);
1104 break;
1105
1106 case WM_NCLBUTTONUP:
1107
1108 bLBMouseDown = FALSE;
1109 DefWindowProc(hwnd,
1110 uMsg,
1111 wParam,
1112 lParam);
1113 break;
1114
1115 case WM_MOVE:
1116 {
1117 /* if the main window is moved, move the toolbars too */
1118 if (bLBMouseDown)
1119 MainWndMoveFloatingWindows(Info, &wndOldPos);
1120 }
1121 break;
1122
1123 case WM_NOTIFY:
1124 {
1125 UINT BarId;
1126 LPNMHDR pnmhdr = (LPNMHDR)lParam;
1127 if (!TbdHandleNotifications(&Info->ToolDocks,
1128 pnmhdr,
1129 &Ret))
1130 {
1131 if (TbdDockBarIdFromClientWindow(&Info->ToolDocks,
1132 pnmhdr->hwndFrom,
1133 &BarId))
1134 {
1135 switch (BarId)
1136 {
1137 case ID_TOOLBAR_TEXT:
1138 switch (pnmhdr->code)
1139 {
1140 case TBN_DELETINGBUTTON:
1141 {
1142 LPNMTOOLBAR lpnmtb = (LPNMTOOLBAR)lParam;
1143
1144 ToolbarDeleteControlSpace(pnmhdr->hwndFrom,
1145 &lpnmtb->tbButton);
1146 break;
1147 }
1148 }
1149 break;
1150 }
1151 }
1152 }
1153 break;
1154 }
1155
1156 case WM_COMMAND:
1157 {
1158 MainWndCommand(Info,
1159 LOWORD(wParam),
1160 (HWND)lParam);
1161 goto HandleDefaultMessage;
1162 }
1163
1164 case WM_MENUSELECT:
1165 {
1166 if (Info->hStatus != NULL)
1167 {
1168 if (!MainWndMenuHint(Info,
1169 LOWORD(wParam),
1170 MainMenuHintTable,
1171 sizeof(MainMenuHintTable) / sizeof(MainMenuHintTable[0]),
1172 IDS_HINT_BLANK))
1173 {
1174 MainWndMenuHint(Info,
1175 LOWORD(wParam),
1176 SystemMenuHintTable,
1177 sizeof(SystemMenuHintTable) / sizeof(SystemMenuHintTable[0]),
1178 IDS_HINT_BLANK);
1179 }
1180 }
1181 break;
1182 }
1183
1184 case WM_ENTERMENULOOP:
1185 {
1186 Info->InMenuLoop = TRUE;
1187 UpdateMainStatusBar(Info);
1188 break;
1189 }
1190
1191 case WM_EXITMENULOOP:
1192 {
1193 Info->InMenuLoop = FALSE;
1194 UpdateMainStatusBar(Info);
1195 break;
1196 }
1197
1198 case WM_CLOSE:
1199 {
1200 DestroyWindow(hwnd);
1201 break;
1202 }
1203
1204 case WM_ENABLE:
1205 {
1206 TbdHandleEnabling(&Info->ToolDocks,
1207 hwnd,
1208 (BOOL)wParam);
1209 goto HandleDefaultMessage;
1210 }
1211
1212 case WM_NCACTIVATE:
1213 {
1214 TbdHandleActivation(&Info->ToolDocks,
1215 hwnd,
1216 &wParam,
1217 &lParam);
1218 goto HandleDefaultMessage;
1219 }
1220
1221 case WM_ACTIVATEAPP:
1222 {
1223 //TbdShowFloatingToolbars(&Info->ToolDocks,
1224 // (BOOL)wParam);
1225 goto HandleDefaultMessage;
1226 }
1227
1228 case WM_CREATE:
1229 {
1230 Info = (PMAIN_WND_INFO)(((LPCREATESTRUCT)lParam)->lpCreateParams);
1231
1232 /* Initialize the main window context */
1233 Info->hSelf = hwnd;
1234
1235 SetWindowLongPtr(hwnd,
1236 GWLP_USERDATA,
1237 (LONG_PTR)Info);
1238
1239 InitMainWnd(Info);
1240
1241 /* Show the window */
1242 ShowWindow(hwnd,
1243 Info->nCmdShow);
1244 /* get the windows position */
1245 GetWindowRect(hwnd,
1246 &wndOldPos);
1247
1248 break;
1249 }
1250
1251 case WM_DESTROY:
1252 {
1253 DestroyMainWnd(Info);
1254
1255 HeapFree(ProcessHeap,
1256 0,
1257 Info);
1258 SetWindowLongPtr(hwnd,
1259 GWLP_USERDATA,
1260 0);
1261
1262 /* Break the message queue loop */
1263 PostQuitMessage(0);
1264 break;
1265 }
1266
1267 default:
1268 {
1269 HandleDefaultMessage:
1270 if (Info != NULL && Info->hMdiClient != NULL)
1271 {
1272 Ret = DefFrameProc(hwnd,
1273 Info->hMdiClient,
1274 uMsg,
1275 wParam,
1276 lParam);
1277 }
1278 else
1279 {
1280 Ret = DefWindowProc(hwnd,
1281 uMsg,
1282 wParam,
1283 lParam);
1284 }
1285 break;
1286 }
1287 }
1288
1289 return Ret;
1290 }
1291
1292 MDI_EDITOR_TYPE
1293 MainWndGetCurrentEditor(PMAIN_WND_INFO MainWnd,
1294 PVOID *Info)
1295 {
1296 MDI_EDITOR_TYPE EditorType;
1297
1298 if (MainWnd->ActiveEditor != NULL)
1299 {
1300 EditorType = *((PMDI_EDITOR_TYPE)MainWnd->ActiveEditor);
1301 *Info = MainWnd->ActiveEditor;
1302 }
1303 else
1304 {
1305 EditorType = metUnknown;
1306 *Info = NULL;
1307 }
1308
1309 return EditorType;
1310 }
1311
1312 VOID
1313 MainWndSwitchEditorContext(PMAIN_WND_INFO Info,
1314 HWND hDeactivate,
1315 HWND hActivate)
1316 {
1317 PMDI_EDITOR_TYPE EditorType;
1318
1319 /* FIXME - optimize light weight switching
1320 when switching from and to an editor of same type */
1321
1322 if (hDeactivate != NULL)
1323 {
1324 EditorType = (PMDI_EDITOR_TYPE)GetWindowLongPtr(hDeactivate,
1325 GWLP_USERDATA);
1326 if (EditorType != NULL)
1327 {
1328 switch (*EditorType)
1329 {
1330 case metImageEditor:
1331 SetImageEditorEnvironment((PEDIT_WND_INFO)EditorType,
1332 FALSE);
1333 break;
1334
1335 default:
1336 break;
1337 }
1338
1339 Info->ActiveEditor = NULL;
1340 }
1341 }
1342
1343 if (hActivate != NULL)
1344 {
1345 EditorType = (PMDI_EDITOR_TYPE)GetWindowLongPtr(hActivate,
1346 GWLP_USERDATA);
1347 if (EditorType != NULL)
1348 {
1349 Info->ActiveEditor = EditorType;
1350
1351 switch (*EditorType)
1352 {
1353 case metImageEditor:
1354 SetImageEditorEnvironment((PEDIT_WND_INFO)EditorType,
1355 TRUE);
1356 break;
1357
1358 default:
1359 break;
1360 }
1361 }
1362 }
1363 }
1364
1365 HWND
1366 CreateMainWindow(LPCTSTR lpCaption,
1367 int nCmdShow)
1368 {
1369 PMAIN_WND_INFO Info;
1370 HWND hMainWnd = NULL;
1371
1372 Info = HeapAlloc(ProcessHeap,
1373 0,
1374 sizeof(MAIN_WND_INFO));
1375 if (Info != NULL)
1376 {
1377 ZeroMemory(Info,
1378 sizeof(MAIN_WND_INFO));
1379 Info->nCmdShow = nCmdShow;
1380
1381 /* FIXME - load the window position from the registry */
1382
1383 hMainWnd = CreateWindowEx(WS_EX_WINDOWEDGE,
1384 szMainWndClass,
1385 lpCaption,
1386 WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
1387 CW_USEDEFAULT,
1388 CW_USEDEFAULT,
1389 CW_USEDEFAULT,
1390 CW_USEDEFAULT,
1391 NULL,
1392 NULL,
1393 hInstance,
1394 Info);
1395 if (hMainWnd == NULL)
1396 {
1397 HeapFree(ProcessHeap,
1398 0,
1399 Info);
1400 }
1401 }
1402
1403 return hMainWnd;
1404 }
1405
1406 BOOL
1407 MainWndTranslateMDISysAccel(HWND hwnd,
1408 LPMSG lpMsg)
1409 {
1410 PMAIN_WND_INFO Info;
1411
1412 /* Get the window context */
1413 Info = (PMAIN_WND_INFO)GetWindowLongPtr(hwnd,
1414 GWLP_USERDATA);
1415 if (Info != NULL && Info->hMdiClient != NULL)
1416 {
1417 return TranslateMDISysAccel(Info->hMdiClient,
1418 lpMsg);
1419 }
1420
1421 return FALSE;
1422 }
1423
1424 BOOL
1425 InitMainWindowImpl(VOID)
1426 {
1427 WNDCLASSEX wc = {0};
1428
1429 wc.cbSize = sizeof(WNDCLASSEX);
1430 wc.lpfnWndProc = MainWndProc;
1431 wc.hInstance = hInstance;
1432 wc.hIcon = LoadIcon(hInstance,
1433 MAKEINTRESOURCE(IDI_IMAGESOFTICON));
1434 wc.hCursor = LoadCursor(NULL,
1435 IDC_ARROW);
1436 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
1437 wc.lpszMenuName = MAKEINTRESOURCE(IDR_MAINMENU);
1438 wc.lpszClassName = szMainWndClass;
1439 wc.hIconSm = (HICON)LoadImage(hInstance,
1440 MAKEINTRESOURCE(IDI_IMAGESOFTICON),
1441 IMAGE_ICON,
1442 16,
1443 16,
1444 LR_SHARED);
1445
1446 return RegisterClassEx(&wc) != (ATOM)0;
1447 }
1448
1449 VOID
1450 UninitMainWindowImpl(VOID)
1451 {
1452 UnregisterClass(szMainWndClass,
1453 hInstance);
1454 }