1 #include "CUIWindow.h"
2 #include "CUIScaler.h"
3 #include "CUIThemes.h"
4 #include "CUIWindowResizer.h"
5 #include <assert.h>
6 #include <commctrl.h>
7 #include <TCFoundation/mystring.h>
8 #include <TCFoundation/TCUserDefaults.h>
9 #include <TCFoundation/TCImage.h>
10 #include <stdio.h>
11
12 static LONG g_checkBoxWidth = 0;
13
14 #if defined(_MSC_VER) && _MSC_VER >= 1400 && defined(_DEBUG)
15 #define new DEBUG_CLIENTBLOCK
16 #endif
17
18 CUIExport int CUIWindow::systemMaxWidth = -1;
19 CUIExport int CUIWindow::systemMaxHeight = -1;
20 CUIExport int CUIWindow::systemMinTrackWidth = -1;
21 CUIExport int CUIWindow::systemMinTrackHeight = -1;
22 CUIExport int CUIWindow::systemMaxTrackWidth = -1;
23 CUIExport int CUIWindow::systemMaxTrackHeight = -1;
24 CUIExport HCURSOR CUIWindow::hArrowCursor = NULL;
25 CUIExport HCURSOR CUIWindow::hWaitCursor = NULL;
26 CUIExport HINSTANCE CUIWindow::hLanguageModule = NULL;
27 CUIExport bool CUIWindow::appVersionPopulated = false;
28 CUIExport DWORD CUIWindow::appVersionMS;
29 CUIExport DWORD CUIWindow::appVersionLS;
30 CUIExport UIntUIntMap CUIWindow::ucMessages;
31
CUIWindow(void)32 CUIWindow::CUIWindow(void)
33 :windowTitle(copyString(_UC(""))),
34 hInstance(NULL),
35 x(0),
36 y(0),
37 width(0),
38 height(0),
39 maxWidth(-1),
40 maxHeight(-1),
41 minWidth(-1),
42 minHeight(-1),
43 hdc(NULL),
44 windowStyle(0),
45 windowClassStyle(0),
46 exWindowStyle(0),
47 hWindow(NULL),
48 hWindowMenu(NULL),
49 parentWindow(NULL),
50 hParentWindow(NULL),
51 initialized(FALSE),
52 created(FALSE),
53 numChildren(0),
54 hBackgroundBrush(NULL),
55 paintStruct(NULL),
56 autosaveName(NULL),
57 scaler(NULL)
58 {
59 init();
60 }
61
CUIWindow(CUCSTR windowTitle,HINSTANCE hInstance,int x,int y,int width,int height)62 CUIWindow::CUIWindow(CUCSTR windowTitle, HINSTANCE hInstance, int x, int y,
63 int width, int height)
64 :windowTitle(copyString(windowTitle)),
65 hInstance(hInstance),
66 x(x),
67 y(y),
68 width(width),
69 height(height),
70 maxWidth(-1),
71 maxHeight(-1),
72 minWidth(-1),
73 minHeight(-1),
74 hdc(NULL),
75 windowStyle(WS_OVERLAPPED | WS_MINIMIZEBOX | WS_MAXIMIZEBOX |
76 WS_SYSMENU | WS_THICKFRAME),
77 windowClassStyle(CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS),
78 exWindowStyle(WS_EX_CONTROLPARENT),
79 hWindow(NULL),
80 hWindowMenu(NULL),
81 parentWindow(NULL),
82 hParentWindow(NULL),
83 initialized(FALSE),
84 created(FALSE),
85 numChildren(0),
86 hBackgroundBrush(NULL),
87 paintStruct(NULL),
88 autosaveName(NULL),
89 scaler(NULL)
90 {
91 init();
92 }
93
CUIWindow(CUIWindow * parentWindow,int x,int y,int width,int height)94 CUIWindow::CUIWindow(CUIWindow* parentWindow, int x, int y, int width,
95 int height)
96 :windowTitle(copyString(_UC(""))),
97 hInstance(parentWindow->getHInstance()),
98 x(x),
99 y(y),
100 width(width),
101 height(height),
102 maxWidth(-1),
103 maxHeight(-1),
104 minWidth(-1),
105 minHeight(-1),
106 hdc(NULL),
107 windowStyle(WS_CHILD | WS_VISIBLE/* | WS_CLIPSIBLINGS*/),
108 windowClassStyle(CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS),
109 exWindowStyle(WS_EX_CONTROLPARENT),
110 hWindow(NULL),
111 hWindowMenu(NULL),
112 parentWindow(parentWindow),
113 hParentWindow(parentWindow->getHWindow()),
114 initialized(FALSE),
115 created(FALSE),
116 numChildren(0),
117 hBackgroundBrush(NULL),
118 paintStruct(NULL),
119 autosaveName(NULL),
120 scaler(NULL)
121 {
122 parentWindow->addChild(this);
123 init();
124 }
125
CUIWindow(HWND hParentWindow,HINSTANCE hInstance,int x,int y,int width,int height)126 CUIWindow::CUIWindow(HWND hParentWindow, HINSTANCE hInstance, int x, int y,
127 int width, int height)
128 :windowTitle(copyString(_UC(""))),
129 x(x),
130 y(y),
131 width(width),
132 height(height),
133 maxWidth(-1),
134 maxHeight(-1),
135 minWidth(-1),
136 minHeight(-1),
137 hdc(NULL),
138 windowStyle(WS_CHILD | WS_VISIBLE/* | WS_CLIPSIBLINGS*/),
139 windowClassStyle(CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS),
140 exWindowStyle(WS_EX_CONTROLPARENT),
141 hInstance(hInstance),
142 hWindow(NULL),
143 hWindowMenu(NULL),
144 parentWindow(NULL),
145 hParentWindow(hParentWindow),
146 initialized(FALSE),
147 created(FALSE),
148 numChildren(0),
149 hBackgroundBrush(NULL),
150 paintStruct(NULL),
151 autosaveName(NULL),
152 scaler(NULL)
153 {
154 // parentWindow->addChild(this);
155 init();
156 }
157
initWindow(void)158 BOOL CUIWindow::initWindow(void)
159 {
160 registerWindowClass();
161 if (createWindow())
162 {
163 initialized = TRUE;
164 return TRUE;
165 }
166 else
167 {
168 return FALSE;
169 }
170 }
171
windowClassName(void)172 const UCCHAR* CUIWindow::windowClassName(void)
173 {
174 if (parentWindow || hParentWindow)
175 {
176 return _UC("CUISubWindow");
177 }
178 else
179 {
180 return _UC("CUIMainWindow");
181 }
182 }
183
~CUIWindow(void)184 CUIWindow::~CUIWindow(void)
185 {
186 }
187
dealloc(void)188 void CUIWindow::dealloc(void)
189 {
190 if (hWindow)
191 {
192 DestroyWindow(hWindow);
193 hWindow = NULL;
194 }
195 if (hWindowMenu)
196 {
197 DestroyMenu(hWindowMenu);
198 hWindowMenu = NULL;
199 }
200 delete windowTitle;
201 windowTitle = NULL;
202 if (!parentWindow)
203 {
204 deleteSystemColorPens();
205 delete systemColors;
206 systemColors = NULL;
207 delete systemColorPens;
208 systemColorPens = NULL;
209 if (hBackgroundBrush)
210 {
211 DeleteObject(hBackgroundBrush);
212 }
213 }
214 delete autosaveName;
215 TCObject::release(scaler);
216 TCObject::dealloc();
217 }
218
closeWindow(void)219 void CUIWindow::closeWindow(void)
220 {
221 DestroyWindow(hWindow);
222 }
223
setArrowCursor(void)224 void CUIWindow::setArrowCursor(void)
225 {
226 if (!hArrowCursor)
227 {
228 hArrowCursor = LoadCursor(NULL, IDC_ARROW);
229 }
230 SetCursor(hArrowCursor);
231 }
232
setWaitCursor(void)233 void CUIWindow::setWaitCursor(void)
234 {
235 if (!hWaitCursor)
236 {
237 hWaitCursor = LoadCursor(NULL, IDC_WAIT);
238 }
239 SetCursor(hWaitCursor);
240 }
241
deleteSystemColorPens(void)242 void CUIWindow::deleteSystemColorPens(void)
243 {
244 if (!parentWindow)
245 {
246 int i;
247
248 for (i = 0; i < NUM_SYSTEM_COLORS; i++)
249 {
250 if (systemColorPens[i])
251 {
252 DeleteObject(systemColorPens[i]);
253 systemColorPens[i] = 0;
254 }
255 }
256 }
257 }
258
init(void)259 void CUIWindow::init(void)
260 {
261 #ifdef _LEAK_DEBUG
262 strcpy(className, "CUIWindow");
263 #endif
264 initUcMessages();
265 initSystemColors();
266 }
267
setRBGFillColor(BYTE r,BYTE g,BYTE b)268 void CUIWindow::setRBGFillColor(BYTE r, BYTE g, BYTE b)
269 {
270 setFillColor(RGB(r, g, b));
271 }
272
setFillColor(DWORD newColor)273 void CUIWindow::setFillColor(DWORD newColor)
274 {
275 fillColor = newColor;
276 }
277
updateSystemColors(void)278 void CUIWindow::updateSystemColors(void)
279 {
280 if (!parentWindow)
281 {
282 int i;
283
284 deleteSystemColorPens();
285 for (i = 0; i < NUM_SYSTEM_COLORS; i++)
286 {
287 systemColors[i] = GetSysColor(i);
288 systemColorPens[i] = CreatePen(PS_SOLID, 0, systemColors[i]);
289 }
290 }
291 }
292
initUcMessages(void)293 void CUIWindow::initUcMessages(void)
294 {
295 ucMessages[WM_SETTEXT] = WM_SETTEXT;
296 ucMessages[WM_GETTEXT] = WM_GETTEXT;
297 ucMessages[CB_DELETESTRING] = CB_DELETESTRING;
298 ucMessages[CB_ADDSTRING] = CB_ADDSTRING;
299 ucMessages[LB_ADDSTRING] = LB_ADDSTRING;
300 ucMessages[CB_SELECTSTRING] = CB_SELECTSTRING;
301 #ifdef TC_NO_UNICODE
302 ucMessages[SB_SETTIPTEXT] = SB_SETTIPTEXTA;
303 ucMessages[SB_GETTIPTEXT] = SB_GETTIPTEXTA;
304 ucMessages[SB_SETTEXT] = SB_SETTEXTA;
305 ucMessages[SB_GETTEXT] = SB_GETTEXTA;
306 ucMessages[TTM_ADDTOOL] = TTM_ADDTOOLA;
307 #else // TC_NO_UNICODE
308 ucMessages[SB_SETTIPTEXT] = SB_SETTIPTEXTW;
309 ucMessages[SB_GETTIPTEXT] = SB_GETTIPTEXTW;
310 ucMessages[SB_SETTEXT] = SB_SETTEXTW;
311 ucMessages[SB_GETTEXT] = SB_GETTEXTW;
312 ucMessages[TTM_ADDTOOL] = TTM_ADDTOOLW;
313 #endif // TC_NO_UNICODE
314 }
315
initSystemColors(void)316 void CUIWindow::initSystemColors(void)
317 {
318 if (parentWindow)
319 {
320 systemColors = parentWindow->systemColors;
321 systemColorPens = parentWindow->systemColorPens;
322 }
323 else
324 {
325 systemColors = new DWORD[NUM_SYSTEM_COLORS];
326 systemColorPens = new HPEN[NUM_SYSTEM_COLORS];
327 memset(systemColorPens, 0, sizeof(HPEN) * NUM_SYSTEM_COLORS);
328 updateSystemColors();
329 }
330 }
331
resize(int newWidth,int newHeight)332 void CUIWindow::resize(int newWidth, int newHeight)
333 {
334 if (initialized)
335 {
336 SIZE decorationSize = {0, 0};
337
338 if (parentWindow)
339 {
340 decorationSize = getDecorationSize();
341 }
342 MoveWindow(hWindow, x - decorationSize.cx / 2, y - decorationSize.cy / 2,
343 newWidth, newHeight, TRUE);
344 }
345 else
346 {
347 width = newWidth;
348 height = newHeight;
349 }
350 }
351
setTimer(UINT timerID,UINT elapse)352 UINT_PTR CUIWindow::setTimer(UINT timerID, UINT elapse)
353 {
354 return SetTimer(hWindow, timerID, elapse, NULL);
355 }
356
killTimer(UINT timerID)357 BOOL CUIWindow::killTimer(UINT timerID)
358 {
359 return KillTimer(hWindow, timerID);
360 }
361
doCommand(int,int,HWND)362 LRESULT CUIWindow::doCommand(int, int, HWND)
363 {
364 return 1;
365 }
366
doTimer(UINT_PTR)367 LRESULT CUIWindow::doTimer(UINT_PTR)
368 {
369 return 1;
370 }
371
doHelp(LPHELPINFO)372 LRESULT CUIWindow::doHelp(LPHELPINFO)
373 {
374 return 0;
375 }
376
doMenuSelect(UINT,UINT,HMENU)377 LRESULT CUIWindow::doMenuSelect(UINT, UINT, HMENU)
378 {
379 return 1;
380 }
381
doThemeChanged(void)382 LRESULT CUIWindow::doThemeChanged(void)
383 {
384 return 1;
385 }
386
doEnterMenuLoop(bool)387 LRESULT CUIWindow::doEnterMenuLoop(bool /*isTrackPopupMenu*/)
388 {
389 return 1;
390 }
391
doExitMenuLoop(bool)392 LRESULT CUIWindow::doExitMenuLoop(bool /*isTrackPopupMenu*/)
393 {
394 return 1;
395 }
396
doInitMenuPopup(HMENU,UINT,BOOL)397 LRESULT CUIWindow::doInitMenuPopup(HMENU /*hPopupMenu*/, UINT /*uPos*/,
398 BOOL /*fSystemMenu*/)
399 {
400 return 0;
401 }
402
doDrawItem(HWND,LPDRAWITEMSTRUCT)403 LRESULT CUIWindow::doDrawItem(HWND /*hControlWnd*/,
404 LPDRAWITEMSTRUCT /*drawItemStruct*/)
405 {
406 return FALSE;
407 }
408
doSize(WPARAM sizeType,int newWidth,int newHeight)409 LRESULT CUIWindow::doSize(WPARAM sizeType, int newWidth, int newHeight)
410 {
411 if (sizeType == SIZE_MINIMIZED)
412 {
413 return 1;
414 }
415 else
416 {
417 int deltaWidth = newWidth - width;
418 int deltaHeight = newHeight - height;
419 int i;
420
421 for (i = 0; i < numChildren; i++)
422 {
423 CUIWindow* child = children[i];
424 SIZE decorationSize = child->getDecorationSize();
425
426 child->resize(child->width + decorationSize.cx + deltaWidth,
427 child->height + decorationSize.cy + deltaHeight);
428 }
429 width = newWidth;
430 height = newHeight;
431 if (autosaveName != NULL)
432 {
433 int saveX, saveY, saveWidth, saveHeight, saveMaximized;
434
435 if (sizeType != SIZE_MAXIMIZED || !readAutosaveInfo(saveX, saveY,
436 saveWidth, saveHeight, saveMaximized))
437 {
438 RECT rect;
439
440 GetWindowRect(hWindow, &rect);
441 saveX = rect.left;
442 saveY = rect.top;
443 saveWidth = rect.right - rect.left;
444 saveHeight = rect.bottom - rect.top;
445 }
446 saveMaximized = sizeType == SIZE_MAXIMIZED;
447 writeAutosaveInfo(saveX, saveY, saveWidth, saveHeight,
448 saveMaximized);
449 }
450 return 0;
451 }
452 }
453
doMove(int newX,int newY)454 LRESULT CUIWindow::doMove(int newX, int newY)
455 {
456 x = newX;
457 y = newY;
458 if (autosaveName != NULL)
459 {
460 if ((GetWindowLong(hWindow, GWL_STYLE) & WS_MAXIMIZE) == 0)
461 {
462 RECT rect;
463 GetWindowRect(hWindow, &rect);
464
465 writeAutosaveInfo(rect.left, rect.top, rect.right - rect.left,
466 rect.bottom - rect.top, 0);
467 }
468 }
469 return 1;
470 }
471
doEraseBackground(RECT *)472 LRESULT CUIWindow::doEraseBackground(RECT *)
473 {
474 created = TRUE;
475 return 0;
476 }
477
getDecorationSize(HMONITOR hMonitor)478 SIZE CUIWindow::getDecorationSize(HMONITOR hMonitor /*= NULL*/)
479 {
480 RECT windowRect = { 0, 0, 100, 100 };
481 WNDCLASSEX windowClass = getWindowClass();
482 SIZE size;
483
484 CUIScaler::adjustWindowRectEx(hMonitor, &windowRect, windowStyle,
485 windowClass.lpszMenuName != NULL || hWindowMenu, exWindowStyle);
486 size.cx = windowRect.right - windowRect.left - 100;
487 size.cy = windowRect.bottom - windowRect.top - 100;
488 if (!(windowStyle & WS_POPUP) && !(windowStyle & WS_CHILD))
489 {
490 size.cx += 2;
491 size.cy += GetSystemMetrics(SM_CYCAPTION) + 2;
492 }
493 return size;
494 }
495
doCreate(HWND hWnd,LPCREATESTRUCT createStruct)496 LRESULT CUIWindow::doCreate(HWND hWnd, LPCREATESTRUCT createStruct)
497 {
498 SIZE decorationSize = getDecorationSize();
499 int dx = decorationSize.cx;
500 int dy = decorationSize.cy;
501 RECT windowRect;
502 int windowWidth;
503 int windowHeight;
504
505 hWindow = hWnd;
506 GetWindowRect(hWnd, &windowRect);
507 windowWidth = windowRect.right - windowRect.left;
508 windowHeight = windowRect.bottom - windowRect.top;
509 if (windowStyle & WS_CHILD)
510 {
511 return 0;
512 }
513 // if (windowStyle & WS_MAXIMIZE)
514 // {
515 // doSize(SIZE_MAXIMIZED, windowWidth - dx, windowHeight - dy);
516 // }
517 if (windowWidth == createStruct->cx && windowHeight == createStruct->cy)
518 {
519 doSize(SIZE_RESTORED, createStruct->cx - dx, createStruct->cy - dy);
520 }
521 else if (windowWidth > createStruct->cx || windowHeight > createStruct->cy)
522 {
523 doSize(SIZE_MAXIMIZED, windowWidth - dx, windowHeight - dy);
524 }
525 else
526 {
527 doSize(SIZE_MINIMIZED, windowWidth - dx, windowHeight - dy);
528 }
529 // x = createStruct->x;
530 // y = createStruct->y;
531 return 0;
532 }
533
doClose(void)534 LRESULT CUIWindow::doClose(void)
535 {
536 return 1;
537 }
538
doDestroy(void)539 LRESULT CUIWindow::doDestroy(void)
540 {
541 return 1;
542 }
543
doNCDestroy(void)544 LRESULT CUIWindow::doNCDestroy(void)
545 {
546 // Clean up.
547 SetWindowLongPtrUC(hWindow, GWLP_USERDATA, (LONG_PTR)NULL);
548 hWindow = NULL;
549 hdc = NULL;
550 hParentWindow = NULL;
551 initialized = FALSE;
552 created = FALSE;
553 return 1;
554 }
555
doPaint(void)556 void CUIWindow::doPaint(void)
557 {
558 }
559
doPostPaint(void)560 void CUIWindow::doPostPaint(void)
561 {
562 }
563
doLButtonDown(WPARAM,int,int)564 LRESULT CUIWindow::doLButtonDown(WPARAM, int, int)
565 {
566 return 1;
567 }
568
doLButtonUp(WPARAM,int,int)569 LRESULT CUIWindow::doLButtonUp(WPARAM, int, int)
570 {
571 return 1;
572 }
573
doLButtonDoubleClick(WPARAM,int,int)574 LRESULT CUIWindow::doLButtonDoubleClick(WPARAM, int, int)
575 {
576 return 1;
577 }
578
doRButtonDown(WPARAM,int,int)579 LRESULT CUIWindow::doRButtonDown(WPARAM, int, int)
580 {
581 return 1;
582 }
583
doRButtonUp(WPARAM,int,int)584 LRESULT CUIWindow::doRButtonUp(WPARAM, int, int)
585 {
586 return 1;
587 }
588
doRButtonDoubleClick(WPARAM,int,int)589 LRESULT CUIWindow::doRButtonDoubleClick(WPARAM, int, int)
590 {
591 return 1;
592 }
593
doMButtonDown(WPARAM,int,int)594 LRESULT CUIWindow::doMButtonDown(WPARAM, int, int)
595 {
596 return 1;
597 }
598
doMButtonUp(WPARAM,int,int)599 LRESULT CUIWindow::doMButtonUp(WPARAM, int, int)
600 {
601 return 1;
602 }
603
doMButtonDoubleClick(WPARAM,int,int)604 LRESULT CUIWindow::doMButtonDoubleClick(WPARAM, int, int)
605 {
606 return 1;
607 }
608
doMouseMove(WPARAM,int,int)609 LRESULT CUIWindow::doMouseMove(WPARAM, int, int)
610 {
611 return 1;
612 }
613
doMouseWheel(short,short,int,int)614 LRESULT CUIWindow::doMouseWheel(short, short, int, int)
615 {
616 return 1;
617 }
618
doCaptureChanged(HWND)619 LRESULT CUIWindow::doCaptureChanged(HWND)
620 {
621 return 1;
622 }
623
doKeyDown(int,LPARAM)624 LRESULT CUIWindow::doKeyDown(int, LPARAM)
625 {
626 return 1;
627 }
628
doKeyUp(int,LPARAM)629 LRESULT CUIWindow::doKeyUp(int, LPARAM)
630 {
631 return 1;
632 }
633
doDropFiles(HDROP)634 LRESULT CUIWindow::doDropFiles(HDROP)
635 {
636 return 1;
637 }
638
doChar(UCCHAR,LPARAM)639 LRESULT CUIWindow::doChar(UCCHAR, LPARAM)
640 {
641 return 1;
642 }
643
doShowWindow(BOOL,LPARAM)644 LRESULT CUIWindow::doShowWindow(BOOL, LPARAM)
645 {
646 return 1;
647 }
648
doActivateApp(BOOL,DWORD)649 LRESULT CUIWindow::doActivateApp(BOOL, DWORD)
650 {
651 return 1;
652 }
653
doActivate(int,BOOL,HWND)654 LRESULT CUIWindow::doActivate(int, BOOL, HWND)
655 {
656 return 1;
657 }
658
redrawChildren(BOOL recurse)659 void CUIWindow::redrawChildren(BOOL recurse)
660 {
661 int i;
662
663 for (i = 0; i < numChildren; i++)
664 {
665 children[i]->doPaint();
666 if (recurse)
667 {
668 children[i]->redrawChildren(TRUE);
669 }
670 }
671 }
672
doSystemColorChange(void)673 void CUIWindow::doSystemColorChange(void)
674 {
675 updateSystemColors();
676 redrawChildren(TRUE);
677 }
678
calcSystemSizes(void)679 void CUIWindow::calcSystemSizes(void)
680 {
681 if (systemMaxWidth == -1)
682 {
683 systemMaxWidth = GetSystemMetrics(SM_CXMAXIMIZED);
684 systemMaxHeight = GetSystemMetrics(SM_CYMAXIMIZED);
685 systemMinTrackWidth = GetSystemMetrics(SM_CXMINTRACK);
686 systemMinTrackHeight = GetSystemMetrics(SM_CYMINTRACK);
687 systemMaxTrackWidth = GetSystemMetrics(SM_CXMAXTRACK);
688 systemMaxTrackHeight = GetSystemMetrics(SM_CYMAXTRACK);
689 }
690 }
691
doNotify(int,LPNMHDR)692 LRESULT CUIWindow::doNotify(int /*controlId*/, LPNMHDR /*notification*/)
693 {
694 return 0;
695 }
696
doGetMinMaxInfo(HWND hWnd,LPMINMAXINFO minMaxInfo)697 LRESULT CUIWindow::doGetMinMaxInfo(HWND hWnd, LPMINMAXINFO minMaxInfo)
698 {
699 if (initialized && (windowStyle & WS_CHILD) == 0)
700 {
701 if (minWidth >= 0 || minHeight >= 0)
702 {
703 int realMaxWidth;
704 int realMaxHeight;
705 int minTrackWidth;
706 int minTrackHeight;
707 int maxTrackWidth;
708 int maxTrackHeight;
709 int decorationWidth;
710 int decorationHeight;
711 RECT clientRect;
712 RECT windowRect;
713
714 GetClientRect(hWnd, &clientRect);
715 GetWindowRect(hWnd, &windowRect);
716 decorationWidth = (windowRect.right - windowRect.left) -
717 (clientRect.right - clientRect.left);
718 decorationHeight = (windowRect.bottom - windowRect.top) -
719 (clientRect.bottom - clientRect.top);
720 calcSystemSizes();
721 int realMinWidth = scalePoints(minWidth);
722 int realMinHeight = scalePoints(minHeight);
723 if (maxWidth == -1)
724 {
725 realMaxWidth = systemMaxWidth;
726 }
727 else
728 {
729 realMaxWidth = maxWidth;
730 }
731 if (maxHeight == -1)
732 {
733 realMaxHeight = systemMaxHeight;
734 }
735 else
736 {
737 realMaxHeight = maxHeight;
738 }
739 if (minWidth == -1)
740 {
741 minTrackWidth = systemMinTrackWidth;
742 }
743 else if (realMinWidth + decorationWidth > systemMaxTrackWidth)
744 {
745 minTrackWidth = systemMaxTrackWidth;
746 }
747 else
748 {
749 minTrackWidth = realMinWidth + decorationWidth;
750 }
751 if (minHeight == -1)
752 {
753 minTrackHeight = systemMinTrackHeight;
754 }
755 else if (realMinHeight + decorationHeight > systemMaxTrackHeight)
756 {
757 minTrackHeight = systemMaxTrackHeight;
758 }
759 else
760 {
761 minTrackHeight = realMinHeight + decorationHeight;
762 }
763 if (maxWidth == -1)
764 {
765 maxTrackWidth = systemMaxTrackWidth;
766 }
767 else
768 {
769 maxTrackWidth = maxWidth;
770 }
771 if (maxHeight == -1)
772 {
773 maxTrackHeight = systemMaxTrackHeight;
774 }
775 else
776 {
777 maxTrackHeight = maxHeight;
778 }
779 minMaxInfo->ptMaxSize.x = realMaxWidth;
780 minMaxInfo->ptMaxSize.y = realMaxHeight;
781 minMaxInfo->ptMinTrackSize.x = minTrackWidth;
782 minMaxInfo->ptMinTrackSize.y = minTrackHeight;
783 minMaxInfo->ptMaxTrackSize.x = maxTrackWidth;
784 minMaxInfo->ptMaxTrackSize.y = maxTrackHeight;
785 return 0;
786 }
787 }
788 return 1;
789 }
790
printMessageName(UINT message)791 void CUIWindow::printMessageName(UINT message)
792 {
793 printf("message: %s\n", getMessageName(message).c_str());
794 }
795
getMessageName(UINT message)796 std::string CUIWindow::getMessageName(UINT message)
797 {
798 switch (message)
799 {
800 case WM_NULL:
801 return "WM_NULL";
802 case WM_CREATE:
803 return "WM_CREATE";
804 case WM_DESTROY:
805 return "WM_DESTROY";
806 case WM_MOVE:
807 return "WM_MOVE";
808 case WM_SIZE:
809 return "WM_SIZE";
810 case WM_ACTIVATE:
811 return "WM_ACTIVATE";
812 case WM_SETFOCUS:
813 return "WM_SETFOCUS";
814 case WM_KILLFOCUS:
815 return "WM_KILLFOCUS";
816 case WM_ENABLE:
817 return "WM_ENABLE";
818 case WM_SETREDRAW:
819 return "WM_SETREDRAW";
820 case WM_SETTEXT:
821 return "WM_SETTEXT";
822 case WM_GETTEXT:
823 return "WM_GETTEXT";
824 case WM_GETTEXTLENGTH:
825 return "WM_GETTEXTLENGTH";
826 case WM_PAINT:
827 return "WM_PAINT";
828 case WM_CLOSE:
829 return "WM_CLOSE";
830 case WM_QUERYENDSESSION:
831 return "WM_QUERYENDSESSION";
832 case WM_QUIT:
833 return "WM_QUIT";
834 case WM_QUERYOPEN:
835 return "WM_QUERYOPEN";
836 case WM_ERASEBKGND:
837 return "WM_ERASEBKGND";
838 case WM_SYSCOLORCHANGE:
839 return "WM_SYSCOLORCHANGE";
840 case WM_ENDSESSION:
841 return "WM_ENDSESSION";
842 case WM_SHOWWINDOW:
843 return "WM_SHOWWINDOW";
844 case WM_SETTINGCHANGE:
845 return "WM_SETTINGCHANGE";
846 case WM_DEVMODECHANGE:
847 return "WM_DEVMODECHANGE";
848 case WM_ACTIVATEAPP:
849 return "WM_ACTIVATEAPP";
850 case WM_FONTCHANGE:
851 return "WM_FONTCHANGE";
852 case WM_TIMECHANGE:
853 return "WM_TIMECHANGE";
854 case WM_CANCELMODE:
855 return "WM_CANCELMODE";
856 case WM_SETCURSOR:
857 return "WM_SETCURSOR";
858 case WM_MOUSEACTIVATE:
859 return "WM_MOUSEACTIVATE";
860 case WM_CHILDACTIVATE:
861 return "WM_CHILDACTIVATE";
862 case WM_QUEUESYNC:
863 return "WM_QUEUESYNC";
864 case WM_GETMINMAXINFO:
865 return "WM_GETMINMAXINFO";
866 case WM_PAINTICON:
867 return "WM_PAINTICON";
868 case WM_ICONERASEBKGND:
869 return "WM_ICONERASEBKGND";
870 case WM_NEXTDLGCTL:
871 return "WM_NEXTDLGCTL";
872 case WM_SPOOLERSTATUS:
873 return "WM_SPOOLERSTATUS";
874 case WM_DRAWITEM:
875 return "WM_DRAWITEM";
876 case WM_MEASUREITEM:
877 return "WM_MEASUREITEM";
878 case WM_DELETEITEM:
879 return "WM_DELETEITEM";
880 case WM_VKEYTOITEM:
881 return "WM_VKEYTOITEM";
882 case WM_CHARTOITEM:
883 return "WM_CHARTOITEM";
884 case WM_SETFONT:
885 return "WM_SETFONT";
886 case WM_GETFONT:
887 return "WM_GETFONT";
888 case WM_SETHOTKEY:
889 return "WM_SETHOTKEY";
890 case WM_GETHOTKEY:
891 return "WM_GETHOTKEY";
892 case WM_QUERYDRAGICON:
893 return "WM_QUERYDRAGICON";
894 case WM_COMPAREITEM:
895 return "WM_COMPAREITEM";
896 case WM_COMPACTING:
897 return "WM_COMPACTING";
898 case WM_COMMNOTIFY:
899 return "WM_COMMNOTIFY";
900 case WM_WINDOWPOSCHANGING:
901 return "WM_WINDOWPOSCHANGING";
902 case WM_WINDOWPOSCHANGED:
903 return "WM_WINDOWPOSCHANGED";
904 case WM_POWER:
905 return "WM_POWER";
906 case WM_COPYDATA:
907 return "WM_COPYDATA";
908 case WM_CANCELJOURNAL:
909 return "WM_CANCELJOURNAL";
910 case WM_NOTIFY:
911 return "WM_NOTIFY";
912 case WM_INPUTLANGCHANGEREQUEST:
913 return "WM_INPUTLANGCHANGEREQUEST";
914 case WM_INPUTLANGCHANGE:
915 return "WM_INPUTLANGCHANGE";
916 case WM_TCARD:
917 return "WM_TCARD";
918 case WM_HELP:
919 return "WM_HELP";
920 case WM_USERCHANGED:
921 return "WM_USERCHANGED";
922 case WM_NOTIFYFORMAT:
923 return "WM_NOTIFYFORMAT";
924 case WM_CONTEXTMENU:
925 return "WM_CONTEXTMENU";
926 case WM_STYLECHANGING:
927 return "WM_STYLECHANGING";
928 case WM_STYLECHANGED:
929 return "WM_STYLECHANGED";
930 case WM_DISPLAYCHANGE:
931 return "WM_DISPLAYCHANGE";
932 case WM_GETICON:
933 return "WM_GETICON";
934 case WM_SETICON:
935 return "WM_SETICON";
936 case WM_NCCREATE:
937 return "WM_NCCREATE";
938 case WM_NCDESTROY:
939 return "WM_NCDESTROY";
940 case WM_NCCALCSIZE:
941 return "WM_NCCALCSIZE";
942 case WM_NCHITTEST:
943 return "WM_NCHITTEST";
944 case WM_NCPAINT:
945 return "WM_NCPAINT";
946 case WM_NCACTIVATE:
947 return "WM_NCACTIVATE";
948 case WM_GETDLGCODE:
949 return "WM_GETDLGCODE";
950 case WM_SYNCPAINT:
951 return "WM_SYNCPAINT";
952 case WM_NCMOUSEMOVE:
953 return "WM_NCMOUSEMOVE";
954 case WM_NCLBUTTONDOWN:
955 return "WM_NCLBUTTONDOWN";
956 case WM_NCLBUTTONUP:
957 return "WM_NCLBUTTONUP";
958 case WM_NCLBUTTONDBLCLK:
959 return "WM_NCLBUTTONDBLCLK";
960 case WM_NCRBUTTONDOWN:
961 return "WM_NCRBUTTONDOWN";
962 case WM_NCRBUTTONUP:
963 return "WM_NCRBUTTONUP";
964 case WM_NCRBUTTONDBLCLK:
965 return "WM_NCRBUTTONDBLCLK";
966 case WM_NCMBUTTONDOWN:
967 return "WM_NCMBUTTONDOWN";
968 case WM_NCMBUTTONUP:
969 return "WM_NCMBUTTONUP";
970 case WM_NCMBUTTONDBLCLK:
971 return "WM_NCMBUTTONDBLCLK";
972 case WM_KEYDOWN:
973 return "WM_KEYDOWN";
974 case WM_KEYUP:
975 return "WM_KEYUP";
976 case WM_CHAR:
977 return "WM_CHAR";
978 case WM_DEADCHAR:
979 return "WM_DEADCHAR";
980 case WM_SYSKEYDOWN:
981 return "WM_SYSKEYDOWN";
982 case WM_SYSKEYUP:
983 return "WM_SYSKEYUP";
984 case WM_SYSCHAR:
985 return "WM_SYSCHAR";
986 case WM_SYSDEADCHAR:
987 return "WM_SYSDEADCHAR";
988 case WM_KEYLAST:
989 return "WM_KEYLAST";
990 case WM_IME_STARTCOMPOSITION:
991 return "WM_IME_STARTCOMPOSITION";
992 case WM_IME_ENDCOMPOSITION:
993 return "WM_IME_ENDCOMPOSITION";
994 case WM_IME_COMPOSITION:
995 return "WM_IME_COMPOSITION";
996 case WM_INITDIALOG:
997 return "WM_INITDIALOG";
998 case WM_COMMAND:
999 return "WM_COMMAND";
1000 case WM_SYSCOMMAND:
1001 return "WM_SYSCOMMAND";
1002 case WM_TIMER:
1003 return "WM_TIMER";
1004 case WM_HSCROLL:
1005 return "WM_HSCROLL";
1006 case WM_VSCROLL:
1007 return "WM_VSCROLL";
1008 case WM_INITMENU:
1009 return "WM_INITMENU";
1010 case WM_INITMENUPOPUP:
1011 return "WM_INITMENUPOPUP";
1012 case WM_MENUSELECT:
1013 return "WM_MENUSELECT";
1014 case WM_MENUCHAR:
1015 return "WM_MENUCHAR";
1016 case WM_ENTERIDLE:
1017 return "WM_ENTERIDLE";
1018 case WM_CTLCOLORMSGBOX:
1019 return "WM_CTLCOLORMSGBOX";
1020 case WM_CTLCOLOREDIT:
1021 return "WM_CTLCOLOREDIT";
1022 case WM_CTLCOLORLISTBOX:
1023 return "WM_CTLCOLORLISTBOX";
1024 case WM_CTLCOLORBTN:
1025 return "WM_CTLCOLORBTN";
1026 case WM_CTLCOLORDLG:
1027 return "WM_CTLCOLORDLG";
1028 case WM_CTLCOLORSCROLLBAR:
1029 return "WM_CTLCOLORSCROLLBAR";
1030 case WM_CTLCOLORSTATIC:
1031 return "WM_CTLCOLORSTATIC";
1032 case WM_MOUSEMOVE:
1033 return "WM_MOUSEMOVE";
1034 case WM_LBUTTONDOWN:
1035 return "WM_LBUTTONDOWN";
1036 case WM_LBUTTONUP:
1037 return "WM_LBUTTONUP";
1038 case WM_LBUTTONDBLCLK:
1039 return "WM_LBUTTONDBLCLK";
1040 case WM_RBUTTONDOWN:
1041 return "WM_RBUTTONDOWN";
1042 case WM_RBUTTONUP:
1043 return "WM_RBUTTONUP";
1044 case WM_RBUTTONDBLCLK:
1045 return "WM_RBUTTONDBLCLK";
1046 case WM_MBUTTONDOWN:
1047 return "WM_MBUTTONDOWN";
1048 case WM_MBUTTONUP:
1049 return "WM_MBUTTONUP";
1050 case WM_MBUTTONDBLCLK:
1051 return "WM_MBUTTONDBLCLK";
1052 case WM_MOUSEWHEEL:
1053 return "WM_MOUSEWHEEL";
1054 case WM_PARENTNOTIFY:
1055 return "WM_PARENTNOTIFY";
1056 case WM_ENTERMENULOOP:
1057 return "WM_ENTERMENULOOP";
1058 case WM_EXITMENULOOP:
1059 return "WM_EXITMENULOOP";
1060 case WM_SIZING:
1061 return "WM_SIZING";
1062 case WM_CAPTURECHANGED:
1063 return "WM_CAPTURECHANGED";
1064 case WM_MOVING:
1065 return "WM_MOVING";
1066 case WM_POWERBROADCAST:
1067 return "WM_POWERBROADCAST";
1068 case WM_DEVICECHANGE:
1069 return "WM_DEVICECHANGE";
1070 case WM_MDICREATE:
1071 return "WM_MDICREATE";
1072 case WM_MDIDESTROY:
1073 return "WM_MDIDESTROY";
1074 case WM_MDIACTIVATE:
1075 return "WM_MDIACTIVATE";
1076 case WM_MDIRESTORE:
1077 return "WM_MDIRESTORE";
1078 case WM_MDINEXT:
1079 return "WM_MDINEXT";
1080 case WM_MDIMAXIMIZE:
1081 return "WM_MDIMAXIMIZE";
1082 case WM_MDITILE:
1083 return "WM_MDITILE";
1084 case WM_MDICASCADE:
1085 return "WM_MDICASCADE";
1086 case WM_MDIICONARRANGE:
1087 return "WM_MDIICONARRANGE";
1088 case WM_MDIGETACTIVE:
1089 return "WM_MDIGETACTIVE";
1090 case WM_MDISETMENU:
1091 return "WM_MDISETMENU";
1092 case WM_ENTERSIZEMOVE:
1093 return "WM_ENTERSIZEMOVE";
1094 case WM_EXITSIZEMOVE:
1095 return "WM_EXITSIZEMOVE";
1096 case WM_DROPFILES:
1097 return "WM_DROPFILES";
1098 case WM_MDIREFRESHMENU:
1099 return "WM_MDIREFRESHMENU";
1100 case WM_IME_SETCONTEXT:
1101 return "WM_IME_SETCONTEXT";
1102 case WM_IME_NOTIFY:
1103 return "WM_IME_NOTIFY";
1104 case WM_IME_CONTROL:
1105 return "WM_IME_CONTROL";
1106 case WM_IME_COMPOSITIONFULL:
1107 return "WM_IME_COMPOSITIONFULL";
1108 case WM_IME_SELECT:
1109 return "WM_IME_SELECT";
1110 case WM_IME_CHAR:
1111 return "WM_IME_CHAR";
1112 case WM_IME_KEYDOWN:
1113 return "WM_IME_KEYDOWN";
1114 case WM_IME_KEYUP:
1115 return "WM_IME_KEYUP";
1116 case WM_MOUSEHOVER:
1117 return "WM_MOUSEHOVER";
1118 case WM_MOUSELEAVE:
1119 return "WM_MOUSELEAVE";
1120 case WM_CUT:
1121 return "WM_CUT";
1122 case WM_COPY:
1123 return "WM_COPY";
1124 case WM_PASTE:
1125 return "WM_PASTE";
1126 case WM_CLEAR:
1127 return "WM_CLEAR";
1128 case WM_UNDO:
1129 return "WM_UNDO";
1130 case WM_RENDERFORMAT:
1131 return "WM_RENDERFORMAT";
1132 case WM_RENDERALLFORMATS:
1133 return "WM_RENDERALLFORMATS";
1134 case WM_DESTROYCLIPBOARD:
1135 return "WM_DESTROYCLIPBOARD";
1136 case WM_DRAWCLIPBOARD:
1137 return "WM_DRAWCLIPBOARD";
1138 case WM_PAINTCLIPBOARD:
1139 return "WM_PAINTCLIPBOARD";
1140 case WM_VSCROLLCLIPBOARD:
1141 return "WM_VSCROLLCLIPBOARD";
1142 case WM_SIZECLIPBOARD:
1143 return "WM_SIZECLIPBOARD";
1144 case WM_ASKCBFORMATNAME:
1145 return "WM_ASKCBFORMATNAME";
1146 case WM_CHANGECBCHAIN:
1147 return "WM_CHANGECBCHAIN";
1148 case WM_HSCROLLCLIPBOARD:
1149 return "WM_HSCROLLCLIPBOARD";
1150 case WM_QUERYNEWPALETTE:
1151 return "WM_QUERYNEWPALETTE";
1152 case WM_PALETTEISCHANGING:
1153 return "WM_PALETTEISCHANGING";
1154 case WM_PALETTECHANGED:
1155 return "WM_PALETTECHANGED";
1156 case WM_HOTKEY:
1157 return "WM_HOTKEY";
1158 case WM_PRINT:
1159 return "WM_PRINT";
1160 case WM_PRINTCLIENT:
1161 return "WM_PRINTCLIENT";
1162 case BM_GETCHECK:
1163 return "BM_GETCHECK";
1164 case BM_SETCHECK:
1165 return "BM_SETCHECK";
1166 case BM_GETSTATE:
1167 return "BM_GETSTATE";
1168 case BM_SETSTATE:
1169 return "BM_SETSTATE";
1170 case BM_SETSTYLE:
1171 return "BM_SETSTYLE";
1172 case BM_CLICK:
1173 return "BM_CLICK";
1174 case BM_GETIMAGE:
1175 return "BM_GETIMAGE";
1176 case BM_SETIMAGE:
1177 return "BM_SETIMAGE";
1178 default:
1179 {
1180 char string[128];
1181
1182 sprintf(string, "0x%04X", message);
1183 return string;
1184 }
1185 }
1186 }
1187
windowProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)1188 LRESULT CUIWindow::windowProc(HWND hWnd, UINT message, WPARAM wParam,
1189 LPARAM lParam)
1190 {
1191 LRESULT rval;
1192 RECT updateRect;
1193
1194 if ((windowClassStyle & CS_OWNDC) && !hdc)
1195 {
1196 hdc = GetDC(hWnd);
1197 }
1198 // printf("%s\n", windowClassName());
1199 // printf("0x%08X 0x%08X 0x%08X ", hWnd, wParam, lParam);
1200 // printMessageName(message);
1201 #ifdef _DEBUG
1202 // _CrtDbgReport(_CRT_WARN, NULL, 0, NULL, "wMsg: 0x%X\n", message);
1203 #endif // _DEBUG
1204 switch (message)
1205 {
1206 case WM_CREATE:
1207 return doCreate(hWnd, (LPCREATESTRUCT)lParam);
1208 break;
1209 case WM_GETMINMAXINFO:
1210 if (!doGetMinMaxInfo(hWnd, (LPMINMAXINFO)lParam))
1211 {
1212 return 0;
1213 }
1214 break;
1215 case WM_SHOWWINDOW:
1216 if (!doShowWindow((BOOL)wParam, lParam))
1217 {
1218 return 0;
1219 }
1220 break;
1221 case WM_ACTIVATEAPP:
1222 if (!doActivateApp((BOOL)wParam, (DWORD)lParam))
1223 {
1224 return 0;
1225 }
1226 break;
1227 case WM_ACTIVATE:
1228 if (!doActivate((int)(unsigned short)LOWORD(wParam),
1229 (BOOL)(unsigned short)HIWORD(wParam), (HWND)lParam))
1230 {
1231 return 0;
1232 }
1233 break;
1234 case WM_SIZE:
1235 if (!doSize(wParam, (int)(short)LOWORD(lParam),
1236 (int)(short)HIWORD(lParam)))
1237 {
1238 return 0;
1239 }
1240 break;
1241 case WM_MOVE:
1242 if (!doMove((int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam)))
1243 {
1244 return 0;
1245 }
1246 break;
1247 case WM_ERASEBKGND:
1248 {
1249 BOOL hadHdc = hdc != NULL;
1250
1251 if (!hadHdc)
1252 {
1253 hdc = (HDC)wParam;
1254 }
1255 if ((rval = doEraseBackground()) != 0)
1256 {
1257 if (!hadHdc)
1258 {
1259 hdc = NULL;
1260 }
1261 return rval;
1262 }
1263 if (!hadHdc)
1264 {
1265 hdc = NULL;
1266 }
1267 }
1268 break;
1269 case WM_CLOSE:
1270 if (!doClose())
1271 {
1272 return 0;
1273 }
1274 break;
1275 case WM_DESTROY:
1276 if (!doDestroy())
1277 {
1278 return 0;
1279 }
1280 break;
1281 case WM_NCDESTROY:
1282 if (!doNCDestroy())
1283 {
1284 return 0;
1285 }
1286 break;
1287 case WM_COMMAND:
1288 if (!doCommand((int)(unsigned short)LOWORD(wParam),
1289 (int)(unsigned short)HIWORD(wParam), (HWND)lParam))
1290 {
1291 return 0;
1292 }
1293 break;
1294 case WM_PAINT:
1295 if (GetUpdateRect(hWnd, &updateRect, FALSE))
1296 {
1297 bool paintStructAllocated = false;
1298
1299 if (!paintStruct)
1300 {
1301 paintStruct = new PAINTSTRUCT;
1302 paintStructAllocated = true;
1303 }
1304 if (windowClassStyle & CS_OWNDC)
1305 {
1306 if (BeginPaint(hWnd, paintStruct))
1307 {
1308 doPaint();
1309 EndPaint(hWnd, paintStruct);
1310 }
1311 }
1312 else
1313 {
1314 hdc = BeginPaint(hWnd, paintStruct);
1315 if (hdc)
1316 {
1317 if (paintStruct->fErase)
1318 {
1319 doEraseBackground(&updateRect);
1320 }
1321 doPaint();
1322 hdc = NULL;
1323 EndPaint(hWnd, paintStruct);
1324 }
1325 }
1326 if (paintStructAllocated)
1327 {
1328 delete paintStruct;
1329 paintStruct = NULL;
1330 }
1331 doPostPaint();
1332 return 0;
1333 }
1334 break;
1335 case WM_LBUTTONDOWN:
1336 if (!doLButtonDown(wParam, (int)(short)LOWORD(lParam),
1337 (int)(short)HIWORD(lParam)))
1338 {
1339 return 0;
1340 }
1341 break;
1342 case WM_LBUTTONUP:
1343 if (!doLButtonUp(wParam, (int)(short)LOWORD(lParam),
1344 (int)(short)HIWORD(lParam)))
1345 {
1346 return 0;
1347 }
1348 break;
1349 case WM_LBUTTONDBLCLK:
1350 if (!doLButtonDoubleClick(wParam, (int)(short)LOWORD(lParam),
1351 (int)(short)HIWORD(lParam)))
1352 {
1353 return 0;
1354 }
1355 break;
1356 case WM_RBUTTONDOWN:
1357 if (!doRButtonDown(wParam, (int)(short)LOWORD(lParam),
1358 (int)(short)HIWORD(lParam)))
1359 {
1360 return 0;
1361 }
1362 break;
1363 case WM_RBUTTONUP:
1364 if (!doRButtonUp(wParam, (int)(short)LOWORD(lParam),
1365 (int)(short)HIWORD(lParam)))
1366 {
1367 return 0;
1368 }
1369 break;
1370 case WM_RBUTTONDBLCLK:
1371 if (!doRButtonDoubleClick(wParam, (int)(short)LOWORD(lParam),
1372 (int)(short)HIWORD(lParam)))
1373 {
1374 return 0;
1375 }
1376 break;
1377 case WM_MBUTTONDOWN:
1378 if (!doMButtonDown(wParam, (int)(short)LOWORD(lParam),
1379 (int)(short)HIWORD(lParam)))
1380 {
1381 return 0;
1382 }
1383 break;
1384 case WM_MBUTTONUP:
1385 if (!doMButtonUp(wParam, (int)(short)LOWORD(lParam),
1386 (int)(short)HIWORD(lParam)))
1387 {
1388 return 0;
1389 }
1390 break;
1391 case WM_MBUTTONDBLCLK:
1392 if (!doMButtonDoubleClick(wParam, (int)(short)LOWORD(lParam),
1393 (int)(short)HIWORD(lParam)))
1394 {
1395 return 0;
1396 }
1397 break;
1398 case WM_MOUSEMOVE:
1399 if (!doMouseMove(wParam, (int)(short)LOWORD(lParam),
1400 (int)(short)HIWORD(lParam)))
1401 {
1402 return 0;
1403 }
1404 break;
1405 case WM_MOUSEWHEEL:
1406 if (!doMouseWheel(LOWORD(wParam), HIWORD(wParam),
1407 (int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam)))
1408 {
1409 return 0;
1410 }
1411 break;
1412 case WM_CAPTURECHANGED:
1413 if (!doCaptureChanged((HWND)lParam))
1414 {
1415 return 0;
1416 }
1417 break;
1418 case WM_KEYDOWN:
1419 if (!doKeyDown((int)wParam, lParam))
1420 {
1421 return 0;
1422 }
1423 break;
1424 case WM_KEYUP:
1425 if (!doKeyUp((int)wParam, lParam))
1426 {
1427 return 0;
1428 }
1429 break;
1430 case WM_DROPFILES:
1431 if (!doDropFiles((HDROP)wParam))
1432 {
1433 return 0;
1434 }
1435 break;
1436 case WM_SYSCOLORCHANGE:
1437 doSystemColorChange();
1438 break;
1439 case WM_CHAR:
1440 if (!doChar((UCCHAR)wParam, lParam))
1441 {
1442 return 0;
1443 }
1444 break;
1445 case WM_TIMER:
1446 if (!lParam && !doTimer((UINT_PTR)wParam))
1447 {
1448 return 0;
1449 }
1450 break;
1451 case WM_HELP:
1452 if (doHelp((LPHELPINFO)lParam))
1453 {
1454 return TRUE;
1455 }
1456 break;
1457 case WM_MENUSELECT:
1458 if (!doMenuSelect(LOWORD(wParam), HIWORD(wParam), (HMENU)lParam))
1459 {
1460 return 0;
1461 }
1462 break;
1463 case WM_ENTERMENULOOP:
1464 if (!doEnterMenuLoop(wParam ? true : false))
1465 {
1466 return 0;
1467 }
1468 break;
1469 case WM_EXITMENULOOP:
1470 if (!doExitMenuLoop(wParam ? true : false))
1471 {
1472 return 0;
1473 }
1474 break;
1475 case WM_INITMENUPOPUP:
1476 if (!doInitMenuPopup((HMENU)wParam, (UINT)LOWORD(lParam),
1477 (BOOL)HIWORD(lParam)))
1478 {
1479 return 0;
1480 }
1481 break;
1482 case WM_DRAWITEM:
1483 if (doDrawItem((HWND)wParam, (LPDRAWITEMSTRUCT)lParam))
1484 {
1485 return TRUE;
1486 }
1487 break;
1488 case WM_THEMECHANGED:
1489 if (!doThemeChanged())
1490 {
1491 return 0;
1492 }
1493 break;
1494 case WM_NOTIFY:
1495 return doNotify((int)(short)LOWORD(wParam), (LPNMHDR)lParam);
1496 break;
1497 case WM_DPICHANGED:
1498 return doDpiChanged((int)(short)LOWORD(wParam), (int)(short)HIWORD(wParam),
1499 (RECT*)lParam);
1500 break;
1501 default:
1502 break;
1503 }
1504 return DefWindowProc(hWnd, message, wParam, lParam);
1505 }
1506
doDpiChanged(int dpiX,int dpiY,RECT * proposedRect)1507 LRESULT CUIWindow::doDpiChanged(int dpiX, int dpiY, RECT* proposedRect)
1508 {
1509 initScaler();
1510 scaler->setDpi(dpiX, dpiY);
1511 if (handleDpiChange())
1512 {
1513 SetWindowPos(hWindow, NULL,
1514 proposedRect->left,
1515 proposedRect->top,
1516 proposedRect->right - proposedRect->left,
1517 proposedRect->bottom - proposedRect->top,
1518 SWP_NOZORDER | SWP_NOACTIVATE);
1519 }
1520 return 0;
1521 }
1522
staticWindowProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)1523 LRESULT CALLBACK CUIWindow::staticWindowProc(HWND hWnd, UINT message,
1524 WPARAM wParam, LPARAM lParam)
1525 {
1526 CUIWindow* cuiWindow = (CUIWindow*)GetWindowLongPtrUC(hWnd, GWLP_USERDATA);
1527
1528 if (!cuiWindow)
1529 {
1530 if (message == WM_CREATE || message == WM_NCCREATE)
1531 {
1532 CREATESTRUCT* createStruct = (LPCREATESTRUCT)lParam;
1533
1534 cuiWindow = (CUIWindow*)(createStruct->lpCreateParams);
1535 if (cuiWindow)
1536 {
1537 SetWindowLongPtrUC(hWnd, GWLP_USERDATA, (LONG_PTR)cuiWindow);
1538 }
1539 }
1540 else
1541 {
1542 return DefWindowProc(hWnd, message, wParam, lParam);
1543 }
1544 }
1545 if (cuiWindow)
1546 {
1547 return cuiWindow->windowProc(hWnd, message, wParam, lParam);
1548 }
1549 else
1550 {
1551 return DefWindowProc(hWnd, message, wParam, lParam);
1552 }
1553 }
1554
disableNonModalWindow(HWND hWnd,LPARAM hModalDialog)1555 BOOL CALLBACK CUIWindow::disableNonModalWindow(HWND hWnd, LPARAM hModalDialog)
1556 {
1557 if (hWnd != (HWND)hModalDialog)
1558 {
1559 EnableWindow(hWnd, FALSE);
1560 }
1561 return TRUE;
1562 }
1563
enableNonModalWindow(HWND hWnd,LPARAM hModalDialog)1564 BOOL CALLBACK CUIWindow::enableNonModalWindow(HWND hWnd, LPARAM hModalDialog)
1565 {
1566 if (hWnd != (HWND)hModalDialog)
1567 {
1568 EnableWindow(hWnd, TRUE);
1569 }
1570 return TRUE;
1571 }
1572
runDialogModal(HWND hDlg,bool allowMessages)1573 void CUIWindow::runDialogModal(HWND hDlg, bool allowMessages)
1574 {
1575 DWORD processId = GetCurrentProcessId();
1576 DWORD dlgProcessId;
1577
1578 if (hDlg == NULL || GetWindowThreadProcessId(hDlg, &dlgProcessId) == 0 ||
1579 processId != dlgProcessId)
1580 {
1581 // If we get garbage input to this function, we end up disabling
1582 // ALL windows on the whole screen, instead of just the LDView ones.
1583 // That makes life difficult on the user.
1584 return;
1585 }
1586 ShowWindow(hDlg, SW_SHOWNORMAL);
1587 EnumThreadWindows(GetWindowThreadProcessId(hDlg, NULL),
1588 disableNonModalWindow, (LPARAM)hDlg);
1589 while (1)
1590 {
1591 MSG msg;
1592
1593 if (!GetMessage(&msg, NULL, 0, 0))
1594 {
1595 doDialogClose(hDlg);
1596 }
1597 if (allowMessages || msg.hwnd == hDlg || IsChild(hDlg, msg.hwnd))
1598 {
1599 if (!IsDialogMessage(hDlg, &msg))
1600 {
1601 TranslateMessage(&msg);
1602 DispatchMessage(&msg);
1603 }
1604 else
1605 {
1606 }
1607 }
1608 else
1609 {
1610 if (msg.message >= WM_MOUSEFIRST && msg.message <= WM_MOUSELAST &&
1611 msg.message != WM_MOUSEMOVE && msg.message != WM_ACTIVATE)
1612 {
1613 MessageBeep(MB_OK);
1614 }
1615 else
1616 {
1617 TranslateMessage(&msg);
1618 DispatchMessage(&msg);
1619 }
1620 }
1621 if (!IsWindow(hDlg) || !IsWindowVisible(hDlg))
1622 {
1623 break;
1624 }
1625 }
1626 }
1627
flushDialogModal(HWND hDlg)1628 bool CUIWindow::flushDialogModal(HWND hDlg)
1629 {
1630 return flushModal(hDlg, true);
1631 }
1632
processModalMessage(MSG msg)1633 void CUIWindow::processModalMessage(MSG msg)
1634 {
1635 TranslateMessage(&msg);
1636 DispatchMessage(&msg);
1637 }
1638
flushModal(HWND hWnd,bool isDialog,int maxFlush)1639 bool CUIWindow::flushModal(HWND hWnd, bool isDialog, int maxFlush)
1640 {
1641 int i = maxFlush;
1642 MSG lastMsg = {0};
1643 bool firstMessage = true;
1644
1645 if (!IsWindowVisible(hWnd))
1646 {
1647 ShowWindow(hWnd, SW_SHOWNORMAL);
1648 }
1649 EnumThreadWindows(GetWindowThreadProcessId(hWnd, NULL),
1650 disableNonModalWindow, (LPARAM)hWnd);
1651 while (1)
1652 {
1653 MSG msg;
1654
1655 if (!PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
1656 {
1657 break;
1658 }
1659 if (msg.message == WM_QUIT)
1660 {
1661 return false;
1662 }
1663 // printf("0x%08x\n", msg.hwnd);
1664 // printMessageName(msg.message);
1665 if (msg.hwnd == hWnd || IsChild(hWnd, msg.hwnd))
1666 {
1667 if (!isDialog || !IsDialogMessage(hWnd, &msg))
1668 {
1669 // This message checking code is a hack, but for some reason
1670 // the toolbar goes into an infinite paint loop if I don't do
1671 // it.
1672 if (firstMessage || lastMsg.hwnd != msg.hwnd ||
1673 lastMsg.message != msg.message)
1674 {
1675 processModalMessage(msg);
1676 }
1677 else
1678 {
1679 if (msg.message == WM_PAINT)
1680 {
1681 // More of the hack: break the infinite paint loop by
1682 // claiming it's no longer needed.
1683 ValidateRect(msg.hwnd, NULL);
1684 }
1685 }
1686 }
1687 else
1688 {
1689 }
1690 }
1691 else
1692 {
1693 if (msg.message >= WM_MOUSEFIRST && msg.message <= WM_MOUSELAST &&
1694 msg.message != WM_MOUSEMOVE && msg.message != WM_ACTIVATE)
1695 {
1696 MessageBeep(MB_OK);
1697 }
1698 else
1699 {
1700 TranslateMessage(&msg);
1701 DispatchMessage(&msg);
1702 }
1703 }
1704 if (!IsWindow(hWnd) || !IsWindowVisible(hWnd))
1705 {
1706 break;
1707 }
1708 if (i-- == 0)
1709 {
1710 break;
1711 }
1712 firstMessage = false;
1713 lastMsg = msg;
1714 }
1715 return true;
1716 }
1717
doDialogClose(HWND hDlg)1718 void CUIWindow::doDialogClose(HWND hDlg)
1719 {
1720 EnumThreadWindows(GetWindowThreadProcessId(hDlg, NULL),
1721 enableNonModalWindow, (LPARAM)hDlg);
1722 ShowWindow(hDlg, SW_HIDE);
1723 }
1724
doDialogThemeChanged(void)1725 BOOL CUIWindow::doDialogThemeChanged(void)
1726 {
1727 return TRUE;
1728 }
1729
doDialogCommand(HWND,int,int,HWND)1730 BOOL CUIWindow::doDialogCommand(HWND, int, int, HWND)
1731 {
1732 return FALSE;
1733 }
1734
doDialogVScroll(HWND,int,int,HWND)1735 BOOL CUIWindow::doDialogVScroll(HWND, int, int, HWND)
1736 {
1737 return FALSE;
1738 }
1739
doDialogHScroll(HWND,int,int,HWND)1740 BOOL CUIWindow::doDialogHScroll(HWND, int, int, HWND)
1741 {
1742 return FALSE;
1743 }
1744
doDialogInit(HWND,HWND,LPARAM)1745 BOOL CUIWindow::doDialogInit(HWND, HWND, LPARAM)
1746 {
1747 return TRUE;
1748 }
1749
doDialogNotify(HWND,int,LPNMHDR)1750 BOOL CUIWindow::doDialogNotify(HWND, int, LPNMHDR)
1751 {
1752 return FALSE;
1753 }
1754
doDialogSize(HWND,WPARAM,int,int)1755 BOOL CUIWindow::doDialogSize(HWND, WPARAM, int, int)
1756 {
1757 return FALSE;
1758 }
1759
doDialogGetMinMaxInfo(HWND,LPMINMAXINFO)1760 BOOL CUIWindow::doDialogGetMinMaxInfo(HWND, LPMINMAXINFO)
1761 {
1762 return FALSE;
1763 }
1764
doDialogChar(HWND,UCCHAR,LPARAM)1765 BOOL CUIWindow::doDialogChar(HWND, UCCHAR, LPARAM)
1766 {
1767 return FALSE;
1768 }
1769
doDialogHelp(HWND,LPHELPINFO)1770 BOOL CUIWindow::doDialogHelp(HWND, LPHELPINFO)
1771 {
1772 return FALSE;
1773 }
1774
doDialogCtlColorStatic(HDC,HWND)1775 BOOL CUIWindow::doDialogCtlColorStatic(HDC /*hdcStatic*/, HWND)
1776 {
1777 return FALSE;
1778 }
1779
doDialogCtlColorBtn(HDC,HWND)1780 BOOL CUIWindow::doDialogCtlColorBtn(HDC /*hdcStatic*/, HWND)
1781 {
1782 return FALSE;
1783 }
1784
dialogProc(HWND hDlg,UINT message,WPARAM wParam,LPARAM lParam)1785 INT_PTR CUIWindow::dialogProc(
1786 HWND hDlg,
1787 UINT message,
1788 WPARAM wParam,
1789 LPARAM lParam)
1790 {
1791 // printf("CUIWindow::dialogProc(0x%04X, 0x%04X, 0x%08X, 0x%08X)\n", hDlg,
1792 // message, wParam, lParam);
1793 BOOL retValue;
1794
1795 switch (message)
1796 {
1797 case WM_INITDIALOG:
1798 return doDialogInit(hDlg, (HWND)wParam, lParam);
1799 break;
1800 case WM_CLOSE:
1801 doDialogClose(hDlg);
1802 break;
1803 case WM_COMMAND:
1804 return doDialogCommand(hDlg, (int)(short)LOWORD(wParam),
1805 (int)(short)HIWORD(wParam), (HWND)lParam);
1806 break;
1807 case WM_VSCROLL:
1808 return doDialogVScroll(hDlg, (int)(short)LOWORD(wParam),
1809 (int)(short)HIWORD(wParam), (HWND)lParam);
1810 break;
1811 case WM_HSCROLL:
1812 return doDialogHScroll(hDlg, (int)(short)LOWORD(wParam),
1813 (int)(short)HIWORD(wParam), (HWND)lParam);
1814 break;
1815 case WM_NOTIFY:
1816 return doDialogNotify(hDlg, (int)(short)LOWORD(wParam),
1817 (LPNMHDR)lParam);
1818 break;
1819 case WM_SIZE:
1820 return doDialogSize(hDlg, wParam, (int)(short)LOWORD(lParam),
1821 (int)(short)HIWORD(lParam));
1822 break;
1823 case WM_GETMINMAXINFO:
1824 return doDialogGetMinMaxInfo(hDlg, (LPMINMAXINFO)lParam);
1825 break;
1826 case WM_CHAR:
1827 return doDialogChar(hDlg, (UCCHAR)wParam, lParam);
1828 break;
1829 case WM_HELP:
1830 return doDialogHelp(hDlg, (LPHELPINFO)lParam);
1831 break;
1832 case WM_THEMECHANGED:
1833 return doDialogThemeChanged();
1834 break;
1835 case WM_CTLCOLORSTATIC:
1836 retValue = doDialogCtlColorStatic((HDC)wParam, (HWND)lParam);
1837 if (retValue)
1838 {
1839 return retValue;
1840 }
1841 break;
1842 case WM_CTLCOLORBTN:
1843 retValue = doDialogCtlColorBtn((HDC)wParam, (HWND)lParam);
1844 if (retValue)
1845 {
1846 return retValue;
1847 }
1848 break;
1849 default:
1850 return FALSE;
1851 break;
1852 }
1853 return FALSE;
1854 }
1855
staticDialogProc(HWND hDlg,UINT message,WPARAM wParam,LPARAM lParam)1856 INT_PTR CALLBACK CUIWindow::staticDialogProc(
1857 HWND hDlg,
1858 UINT message,
1859 WPARAM wParam,
1860 LPARAM lParam)
1861 {
1862 CUIWindow* cuiWindow;
1863
1864 // debugPrintf("CUIWindow::staticDialogProc\n");
1865 // printMessageName(message);
1866 if (message == WM_INITDIALOG)
1867 {
1868 cuiWindow = (CUIWindow*)lParam;
1869 SetWindowLongPtrUC(hDlg, DWLP_USER, lParam);
1870 }
1871 else
1872 {
1873 cuiWindow = (CUIWindow*)GetWindowLongPtrUC(hDlg, DWLP_USER);
1874 }
1875 if (cuiWindow)
1876 {
1877 return cuiWindow->dialogProc(hDlg, message, wParam, lParam);
1878 }
1879 else
1880 {
1881 return FALSE;
1882 }
1883 }
1884
populateAppVersion(void)1885 void CUIWindow::populateAppVersion(void)
1886 {
1887 if (!appVersionPopulated)
1888 {
1889 UCCHAR appFilename[1024];
1890
1891 if (GetModuleFileName(NULL, appFilename, COUNT_OF(appFilename)) > 0)
1892 {
1893 DWORD zero;
1894 DWORD versionInfoSize = GetFileVersionInfoSize(appFilename, &zero);
1895
1896 if (versionInfoSize > 0)
1897 {
1898 BYTE *versionInfo = new BYTE[versionInfoSize];
1899
1900 if (GetFileVersionInfo(appFilename, NULL, versionInfoSize,
1901 versionInfo))
1902 {
1903 VS_FIXEDFILEINFO *fixedVersionInfo;
1904 UINT versionLength;
1905
1906 if (VerQueryValue(versionInfo, _UC("\\"),
1907 (void**)&fixedVersionInfo, &versionLength))
1908 {
1909 appVersionMS = fixedVersionInfo->dwProductVersionMS;
1910 appVersionLS = fixedVersionInfo->dwProductVersionLS;
1911 appVersionPopulated = true;
1912 }
1913 }
1914 delete[] versionInfo;
1915 }
1916 }
1917 }
1918 }
1919
loadLanguageModule(LCID lcid,bool includeSub)1920 bool CUIWindow::loadLanguageModule(LCID lcid, bool includeSub)
1921 {
1922 UCCHAR localeInfo[1024];
1923 LCTYPE lcType = LOCALE_SENGLANGUAGE;
1924
1925 if (includeSub)
1926 {
1927 lcType = LOCALE_SLANGUAGE;
1928 }
1929 if (GetLocaleInfo(lcid, lcType, localeInfo, COUNT_OF(localeInfo)) > 0)
1930 {
1931 const char *appName = TCUserDefaults::getAppName();
1932 UCCHAR languageModuleName[1024];
1933 UCSTR nameOverride =
1934 TCUserDefaults::stringForKeyUC("LanguageModuleName", NULL, false);
1935
1936 if (strchr(appName, '/'))
1937 {
1938 appName = strrchr(appName, '/') + 1;
1939 }
1940 if (strchr(appName, '\\'))
1941 {
1942 appName = strrchr(appName, '\\') + 1;
1943 }
1944 if (nameOverride)
1945 {
1946 ucstrcpy(languageModuleName, nameOverride);
1947 delete[] nameOverride;
1948 }
1949 else
1950 {
1951 ucstring ucAppName;
1952 utf8toucstring(ucAppName, appName);
1953 sucprintf(languageModuleName, COUNT_OF(languageModuleName),
1954 _UC("%s-%s.dll"), ucAppName.c_str(), localeInfo);
1955 }
1956 hLanguageModule = LoadLibrary(languageModuleName);
1957 if (hLanguageModule)
1958 {
1959 DWORD (*getCUIAppLanguageModuleVersion)(const char *, int) =
1960 (DWORD (*)(const char *, int))GetProcAddress(hLanguageModule,
1961 "getCUIAppLanguageModuleVersion");
1962
1963 if (getCUIAppLanguageModuleVersion)
1964 {
1965 DWORD dllVersionMS;
1966 DWORD dllVersionLS;
1967
1968 dllVersionMS = getCUIAppLanguageModuleVersion(appName, 0);
1969 dllVersionLS = getCUIAppLanguageModuleVersion(appName, 1);
1970 // Note that we don't care about the least significant version
1971 // part, so we mask that part out of our comparison.
1972 if (dllVersionMS != appVersionMS ||
1973 (dllVersionLS & 0xFFFF0000) != (appVersionLS & 0xFFFF0000))
1974 {
1975 UCCHAR message[1024];
1976
1977 sucprintf(message, COUNT_OF(message),
1978 _UC("Language module %s found.\n")
1979 _UC("This language module was created for a different ")
1980 _UC("version of LDView, and therefore cannot be used."),
1981 languageModuleName);
1982 MessageBox(NULL, message, _UC("Wrong Language Module"),
1983 MB_ICONWARNING | MB_OK);
1984 FreeLibrary(hLanguageModule);
1985 hLanguageModule = NULL;
1986 }
1987 }
1988 else
1989 {
1990 FreeLibrary(hLanguageModule);
1991 hLanguageModule = NULL;
1992 }
1993 }
1994 }
1995 if (includeSub && hLanguageModule == NULL)
1996 {
1997 return loadLanguageModule(lcid, false);
1998 }
1999 else
2000 {
2001 return hLanguageModule != NULL;
2002 }
2003 }
2004
populateLanguageModule(HINSTANCE hDefaultModule)2005 void CUIWindow::populateLanguageModule(HINSTANCE hDefaultModule)
2006 {
2007 if (!hLanguageModule)
2008 {
2009 populateAppVersion();
2010 if (!loadLanguageModule(LOCALE_USER_DEFAULT))
2011 {
2012 hLanguageModule = hDefaultModule;
2013 }
2014 }
2015 }
2016
getLanguageModule(void)2017 HINSTANCE CUIWindow::getLanguageModule(void)
2018 {
2019 if (!hLanguageModule)
2020 {
2021 populateLanguageModule(GetModuleHandle(NULL));
2022 }
2023 return hLanguageModule;
2024 }
2025
createDialog(UCSTR templateName,BOOL asChildWindow,DLGPROC dialogProc,LPARAM lParam)2026 HWND CUIWindow::createDialog(UCSTR templateName, BOOL asChildWindow,
2027 DLGPROC dialogProc, LPARAM lParam)
2028 {
2029 HWND hWnd;
2030
2031 if (asChildWindow)
2032 {
2033 hWnd = hWindow;
2034 }
2035 else
2036 {
2037 hWnd = NULL;
2038 }
2039 if (!lParam)
2040 {
2041 lParam = (LPARAM)this;
2042 }
2043 HWND hDlg = CreateDialogParamUC(getLanguageModule(), templateName, hWnd,
2044 dialogProc, lParam);
2045 fixDialogSizes(hDlg);
2046 return hDlg;
2047 }
2048
createDialog(int templateNumber,BOOL asChildWindow,DLGPROC dialogProc,LPARAM lParam)2049 HWND CUIWindow::createDialog(int templateNumber, BOOL asChildWindow,
2050 DLGPROC dialogProc, LPARAM lParam)
2051 {
2052 return createDialog(MAKEINTRESOURCEUC(templateNumber), asChildWindow,
2053 dialogProc, lParam);
2054 }
2055
getBackgroundBrush(void)2056 HBRUSH CUIWindow::getBackgroundBrush(void)
2057 {
2058 if (!hBackgroundBrush)
2059 {
2060 hBackgroundBrush = CreateSolidBrush(RGB(0, 0, 0));
2061 }
2062 return hBackgroundBrush;
2063 // return (HBRUSH)(COLOR_WINDOW + 1);
2064 }
2065
getWindowClass(void)2066 WNDCLASSEX CUIWindow::getWindowClass(void)
2067 {
2068 WNDCLASSEX windowClass;
2069
2070 // Set up and window class
2071 windowClass.cbSize = sizeof(windowClass);
2072 windowClass.style = windowClassStyle;
2073 windowClass.lpfnWndProc = staticWindowProc;
2074 windowClass.cbClsExtra = 0;
2075 windowClass.cbWndExtra = 0;
2076 windowClass.hInstance = getLanguageModule();
2077 windowClass.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
2078 windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
2079 windowClass.hbrBackground = getBackgroundBrush();
2080 windowClass.lpszMenuName = NULL;
2081 windowClass.lpszClassName = windowClassName();
2082 windowClass.hIconSm = LoadIcon(hInstance, IDI_APPLICATION);
2083 return windowClass;
2084 }
2085
registerWindowClass(void)2086 void CUIWindow::registerWindowClass(void)
2087 {
2088 WNDCLASSEX windowClass;
2089
2090 if (!GetClassInfoEx(getLanguageModule(), windowClassName(), &windowClass))
2091 {
2092 windowClass = getWindowClass();
2093 RegisterClassEx(&windowClass);
2094 }
2095 }
2096
setTitle(CUCSTR value)2097 void CUIWindow::setTitle(CUCSTR value)
2098 {
2099 delete windowTitle;
2100 windowTitle = copyString(value);
2101 if (hWindow)
2102 {
2103 setWindowTextUC(hWindow, windowTitle);
2104 }
2105 }
2106
createMainWindow(void)2107 BOOL CUIWindow::createMainWindow(void)
2108 {
2109 POINT point = { 0, 0 };
2110 if (x != CW_USEDEFAULT)
2111 {
2112 point.x = x;
2113 point.y = y;
2114 }
2115 HMONITOR hMonitor = MonitorFromPoint(point, MONITOR_DEFAULTTOPRIMARY);
2116 SIZE decorationSize = getDecorationSize(hMonitor);
2117 int dx = decorationSize.cx;
2118 int dy = decorationSize.cy;
2119 double scaleFactor = CUIScaler::getScaleFactor(hMonitor);
2120 if (x != CW_USEDEFAULT)
2121 {
2122 x = (int)(x * scaleFactor);
2123 y = (int)(y * scaleFactor);
2124 }
2125 int totalWidth = (int)(width * scaleFactor) + dx;
2126 int totalHeight = (int)(height * scaleFactor) + dy;
2127 hWindow = CreateWindowEx(exWindowStyle, windowClassName(), windowTitle,
2128 windowStyle, x, y, totalWidth, totalHeight, NULL, hWindowMenu,
2129 getLanguageModule(), this);
2130 if (!hWindow)
2131 {
2132 DWORD error = GetLastError();
2133
2134 if (error)
2135 {
2136 return FALSE;
2137 }
2138 }
2139 SetWindowLongPtrUC(hWindow, GWLP_USERDATA, (LONG_PTR)this);
2140 return TRUE;
2141 }
2142
createSubWindow(void)2143 BOOL CUIWindow::createSubWindow(void)
2144 {
2145 SIZE decorationSize = getDecorationSize();
2146 int dx = decorationSize.cx;
2147 int dy = decorationSize.cy;
2148
2149 dx = 0;
2150 dy = 0;
2151 if (!hParentWindow)
2152 {
2153 hParentWindow = parentWindow->hWindow;
2154 }
2155 hWindow = CreateWindowEx(exWindowStyle, windowClassName(), windowTitle,
2156 windowStyle, x - dx / 2, y - dy / 2, width, height, hParentWindow,
2157 hWindowMenu, getLanguageModule(), this);
2158 if (!hWindow)
2159 {
2160 DWORD error = GetLastError();
2161
2162 if (error)
2163 {
2164 return FALSE;
2165 }
2166 }
2167 SetWindowLongPtrUC(hWindow, GWLP_USERDATA, (LONG_PTR)this);
2168 return TRUE;
2169 }
2170
createWindow(void)2171 BOOL CUIWindow::createWindow(void)
2172 {
2173 if (parentWindow || hParentWindow)
2174 {
2175 return createSubWindow();
2176 }
2177 else
2178 {
2179 return createMainWindow();
2180 }
2181 }
2182
showWindow(int nCmdShow)2183 void CUIWindow::showWindow(int nCmdShow)
2184 {
2185 ShowWindow(hWindow, nCmdShow);
2186 UpdateWindow(hWindow);
2187 }
2188
maximize(void)2189 void CUIWindow::maximize(void)
2190 {
2191 // printf("About to maximize...\n");
2192 showWindow(SW_MAXIMIZE);
2193 // printf("Maximized.\n");
2194 }
2195
minimize(void)2196 void CUIWindow::minimize(void)
2197 {
2198 showWindow(SW_MINIMIZE);
2199 }
2200
restore(void)2201 void CUIWindow::restore(void)
2202 {
2203 showWindow(SW_RESTORE);
2204 }
2205
addChild(CUIWindow * childWindow)2206 void CUIWindow::addChild(CUIWindow* childWindow)
2207 {
2208 if (numChildren < CUI_MAX_CHILDREN)
2209 {
2210 children[numChildren] = childWindow;
2211 numChildren++;
2212 }
2213 }
2214
removeChild(CUIWindow * childWindow)2215 void CUIWindow::removeChild(CUIWindow* childWindow)
2216 {
2217 int i;
2218
2219 for (i = 0; i < numChildren && children[i] != childWindow; i++)
2220 {
2221 }
2222 for (i++; i < numChildren; i++)
2223 {
2224 children[i-1] = children[i];
2225 }
2226 numChildren--;
2227 }
2228
copyToClipboard(const char * value)2229 bool CUIWindow::copyToClipboard(const char *value)
2230 {
2231 size_t len = strlen(value) + 1;
2232 HGLOBAL hBuf = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, len);
2233
2234 if (hBuf)
2235 {
2236 char *buf = (char*)GlobalLock(hBuf);
2237
2238 strcpy(buf, value);
2239 GlobalUnlock(hBuf);
2240 if (OpenClipboard(hWindow))
2241 {
2242 EmptyClipboard();
2243 SetClipboardData(CF_OEMTEXT, hBuf);
2244 CloseClipboard();
2245 return true;
2246 }
2247 else
2248 {
2249 GlobalFree(hBuf);
2250 }
2251 }
2252 return false;
2253 }
2254
2255 #ifndef TC_NO_UNICODE
copyToClipboard(const wchar_t * value)2256 bool CUIWindow::copyToClipboard(const wchar_t *value)
2257 {
2258 size_t len = wcslen(value) + 1;
2259 HGLOBAL hBuf = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,
2260 len * sizeof(wchar_t));
2261
2262 if (hBuf)
2263 {
2264 wchar_t *buf = (wchar_t*)GlobalLock(hBuf);
2265
2266 wcscpy(buf, value);
2267 GlobalUnlock(hBuf);
2268 if (OpenClipboard(hWindow))
2269 {
2270 EmptyClipboard();
2271 SetClipboardData(CF_UNICODETEXT, hBuf);
2272 CloseClipboard();
2273 return true;
2274 }
2275 else
2276 {
2277 GlobalFree(hBuf);
2278 }
2279 }
2280 return false;
2281 }
2282 #endif // TC_NO_UNICODE
2283
findSubMenu(HMENU hParentMenu,int subMenuIndex,int * index)2284 HMENU CUIWindow::findSubMenu(HMENU hParentMenu, int subMenuIndex, int *index)
2285 {
2286 int i;
2287 int count = GetMenuItemCount(hParentMenu);
2288 int foundCount = 0;
2289 MENUITEMINFO itemInfo;
2290
2291 memset(&itemInfo, 0, sizeof(MENUITEMINFO));
2292 itemInfo.cbSize = sizeof(MENUITEMINFO);
2293 itemInfo.fMask = MIIM_DATA | MIIM_SUBMENU;
2294 for (i = 0; i < count; i++)
2295 {
2296 GetMenuItemInfo(hParentMenu, i, TRUE, &itemInfo);
2297 if (itemInfo.hSubMenu)
2298 {
2299 if (foundCount == subMenuIndex)
2300 {
2301 if (index)
2302 {
2303 *index = i;
2304 }
2305 return itemInfo.hSubMenu;
2306 }
2307 foundCount++;
2308 }
2309 }
2310 return NULL;
2311 }
2312
2313 // Note: static method.
createWindowExUC(DWORD dwExStyle,CUCSTR lpClassName,CUCSTR lpWindowName,DWORD dwStyle,int x,int y,int nWidth,int nHeight,HWND hWndParent,HMENU hMenu,HINSTANCE hInstance,LPVOID lpParam)2314 HWND CUIWindow::createWindowExUC(DWORD dwExStyle, CUCSTR lpClassName,
2315 CUCSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth,
2316 int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance,
2317 LPVOID lpParam)
2318 {
2319 #ifdef TC_NO_UNICODE
2320 return ::CreateWindowExA(dwExStyle, lpClassName, lpWindowName, dwStyle, x,
2321 y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
2322 #else // TC_NO_UNICODE
2323 return ::CreateWindowExW(dwExStyle, lpClassName, lpWindowName, dwStyle, x,
2324 y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
2325 #endif // TC_NO_UNICODE
2326 }
2327
2328 // Note: static method.
setWindowTextUC(HWND hWnd,CUCSTR text)2329 BOOL CUIWindow::setWindowTextUC(HWND hWnd, CUCSTR text)
2330 {
2331 #ifdef TC_NO_UNICODE
2332 return ::SetWindowTextA(hWnd, text);
2333 #else // TC_NO_UNICODE
2334 return ::SetWindowTextW(hWnd, text);
2335 #endif // TC_NO_UNICODE
2336 }
2337
2338 // Note: static method.
sendMessageUC(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)2339 LRESULT CUIWindow::sendMessageUC(
2340 HWND hWnd,
2341 UINT uMsg,
2342 WPARAM wParam,
2343 LPARAM lParam)
2344 {
2345 UINT actualMessage = ucMessages[uMsg];
2346
2347 assert(actualMessage);
2348 #ifdef TC_NO_UNICODE
2349 return ::SendMessageA(hWnd, actualMessage, wParam, lParam);
2350 #else // TC_NO_UNICODE
2351 return ::SendMessageW(hWnd, actualMessage, wParam, lParam);
2352 #endif // TC_NO_UNICODE
2353 }
2354
2355 // Note: static method.
sendDlgItemMessageUC(HWND hDlg,int nIDDlgItem,UINT uMsg,WPARAM wParam,LPARAM lParam)2356 LRESULT CUIWindow::sendDlgItemMessageUC(
2357 HWND hDlg,
2358 int nIDDlgItem,
2359 UINT uMsg,
2360 WPARAM wParam,
2361 LPARAM lParam)
2362 {
2363 UINT actualMessage = ucMessages[uMsg];
2364
2365 assert(actualMessage);
2366 #ifdef TC_NO_UNICODE
2367 return ::SendDlgItemMessageA(hDlg, nIDDlgItem, actualMessage, wParam,
2368 lParam);
2369 #else // TC_NO_UNICODE
2370 return ::SendDlgItemMessageW(hDlg, nIDDlgItem, actualMessage, wParam,
2371 lParam);
2372 #endif // TC_NO_UNICODE
2373 }
2374
2375 // Note: static method.
messageBoxUC(HWND hWnd,CUCSTR lpText,CUCSTR lpCaption,UINT uType)2376 int CUIWindow::messageBoxUC(
2377 HWND hWnd,
2378 CUCSTR lpText,
2379 CUCSTR lpCaption,
2380 UINT uType)
2381 {
2382 #ifdef TC_NO_UNICODE
2383 return ::MessageBoxA(hWnd, lpText, lpCaption, uType);
2384 #else // TC_NO_UNICODE
2385 return ::MessageBoxW(hWnd, lpText, lpCaption, uType);
2386 #endif // TC_NO_UNICODE
2387 }
2388
2389 // Note: static method.
createStatusWindowUC(LONG style,CUCSTR lpszText,HWND hwndParent,UINT wID)2390 HWND CUIWindow::createStatusWindowUC(
2391 LONG style,
2392 CUCSTR lpszText,
2393 HWND hwndParent,
2394 UINT wID)
2395 {
2396 #ifdef TC_NO_UNICODE
2397 return ::CreateStatusWindowA(style, lpszText, hwndParent, wID);
2398 #else // TC_NO_UNICODE
2399 return ::CreateStatusWindowW(style, lpszText, hwndParent, wID);
2400 #endif // TC_NO_UNICODE
2401 }
2402
2403 // Note: static method.
insertMenuItemUC(HMENU hmenu,UINT item,BOOL fByPosition,MENUITEMINFOUC * lpmi)2404 BOOL CUIWindow::insertMenuItemUC(
2405 HMENU hmenu,
2406 UINT item,
2407 BOOL fByPosition,
2408 MENUITEMINFOUC *lpmi)
2409 {
2410 #ifdef TC_NO_UNICODE
2411 return ::InsertMenuItemA(hmenu, item, fByPosition, lpmi);
2412 #else // TC_NO_UNICODE
2413 return ::InsertMenuItemW(hmenu, item, fByPosition, lpmi);
2414 #endif // TC_NO_UNICODE
2415 }
2416
2417 // Note: static method.
getOpenFileNameUC(OPENFILENAMEUC * lpofn)2418 BOOL CUIWindow::getOpenFileNameUC(OPENFILENAMEUC *lpofn)
2419 {
2420 #ifdef TC_NO_UNICODE
2421 return ::GetOpenFileNameA(lpofn);
2422 #else // TC_NO_UNICODE
2423 return ::GetOpenFileNameW(lpofn);
2424 #endif // TC_NO_UNICODE
2425 }
2426
2427
2428 // Note: static method
getTextExtentPoint32UC(HDC hdc,CUCSTR lpString,int cbString,LPSIZE lpSize)2429 BOOL CUIWindow::getTextExtentPoint32UC(
2430 HDC hdc,
2431 CUCSTR lpString,
2432 int cbString,
2433 LPSIZE lpSize)
2434 {
2435 #ifdef TC_NO_UNICODE
2436 return ::GetTextExtentPoint32A(hdc, lpString, cbString, lpSize);
2437 #else // TC_NO_UNICODE
2438 return ::GetTextExtentPoint32W(hdc, lpString, cbString, lpSize);
2439 #endif // TC_NO_UNICODE
2440 }
2441
2442 // Note: static method.
screenToClient(HWND hWnd,RECT * rect)2443 BOOL CUIWindow::screenToClient(HWND hWnd, RECT *rect)
2444 {
2445 POINT tempPoint = {rect->left, rect->top};
2446 if (::ScreenToClient(hWnd, &tempPoint))
2447 {
2448 rect->left = tempPoint.x;
2449 rect->top = tempPoint.y;
2450 tempPoint.x = rect->right;
2451 tempPoint.y = rect->bottom;
2452 if (::ScreenToClient(hWnd, &tempPoint))
2453 {
2454 rect->right = tempPoint.x;
2455 rect->bottom = tempPoint.y;
2456 return TRUE;
2457 }
2458 }
2459 return FALSE;
2460 }
2461
2462 // Note: static method.
clientToScreen(HWND hWnd,RECT * rect)2463 BOOL CUIWindow::clientToScreen(HWND hWnd, RECT *rect)
2464 {
2465 POINT tempPoint = {rect->left, rect->top};
2466 if (::ClientToScreen(hWnd, &tempPoint))
2467 {
2468 rect->left = tempPoint.x;
2469 rect->top = tempPoint.y;
2470 tempPoint.x = rect->right;
2471 tempPoint.y = rect->bottom;
2472 if (::ClientToScreen(hWnd, &tempPoint))
2473 {
2474 rect->right = tempPoint.x;
2475 rect->bottom = tempPoint.y;
2476 return TRUE;
2477 }
2478 }
2479 return FALSE;
2480 }
2481
2482 // Note: static method
setMenuCheck(HMENU hParentMenu,UINT uItem,bool checked,bool radio)2483 void CUIWindow::setMenuCheck(
2484 HMENU hParentMenu,
2485 UINT uItem,
2486 bool checked,
2487 bool radio)
2488 {
2489 MENUITEMINFO itemInfo;
2490 //char title[256];
2491
2492 memset(&itemInfo, 0, sizeof(MENUITEMINFO));
2493 itemInfo.cbSize = sizeof(MENUITEMINFO);
2494 itemInfo.fMask = MIIM_STATE;// | MIIM_TYPE;
2495 //itemInfo.fType = MFT_STRING;
2496 //itemInfo.dwTypeData = title;
2497 //itemInfo.cch = 256;
2498 GetMenuItemInfo(hParentMenu, uItem, FALSE, &itemInfo);
2499 if (checked)
2500 {
2501 itemInfo.fState |= MFS_CHECKED;
2502 itemInfo.fState &= ~MFS_UNCHECKED;
2503 }
2504 else
2505 {
2506 itemInfo.fState &= ~MFS_CHECKED;
2507 itemInfo.fState |= MFS_UNCHECKED;
2508 }
2509 itemInfo.fType = MFT_STRING;
2510 if (radio)
2511 {
2512 itemInfo.fType |= MFT_RADIOCHECK;
2513 }
2514 SetMenuItemInfo(hParentMenu, uItem, FALSE, &itemInfo);
2515 }
2516
2517 // Note: static method
setMenuRadioCheck(HMENU hParentMenu,UINT uItem,bool checked)2518 void CUIWindow::setMenuRadioCheck(HMENU hParentMenu, UINT uItem, bool checked)
2519 {
2520 setMenuCheck(hParentMenu, uItem, checked, true);
2521 }
2522
2523 // Note: static method
getMenuCheck(HMENU hParentMenu,UINT uItem)2524 bool CUIWindow::getMenuCheck(HMENU hParentMenu, UINT uItem)
2525 {
2526 MENUITEMINFO itemInfo;
2527
2528 memset(&itemInfo, 0, sizeof(MENUITEMINFO));
2529 itemInfo.cbSize = sizeof(MENUITEMINFO);
2530 itemInfo.fMask = MIIM_STATE;
2531 GetMenuItemInfo(hParentMenu, uItem, FALSE, &itemInfo);
2532 return (itemInfo.fState & MFS_CHECKED) != 0;
2533 }
2534
setMenuItemsEnabled(HMENU hMenu,bool enabled)2535 void CUIWindow::setMenuItemsEnabled(HMENU hMenu, bool enabled)
2536 {
2537 int i;
2538 int count = GetMenuItemCount(hMenu);
2539
2540 for (i = 0; i < count; i++)
2541 {
2542 setMenuEnabled(hMenu, i, enabled, TRUE);
2543 }
2544 }
2545
setMenuEnabled(HMENU hParentMenu,int itemID,bool enabled,BOOL byPosition)2546 void CUIWindow::setMenuEnabled(
2547 HMENU hParentMenu,
2548 int itemID,
2549 bool enabled,
2550 BOOL byPosition)
2551 {
2552 MENUITEMINFO itemInfo;
2553 //BYTE tbState = 0;
2554
2555 itemInfo.cbSize = sizeof(itemInfo);
2556 itemInfo.fMask = MIIM_STATE;
2557 if (GetMenuItemInfo(hParentMenu, itemID, byPosition, &itemInfo))
2558 {
2559 if (enabled)
2560 {
2561 itemInfo.fState &= ~MFS_DISABLED;
2562 }
2563 else
2564 {
2565 itemInfo.fState |= MFS_DISABLED;
2566 }
2567 itemInfo.fMask = MIIM_STATE;
2568 SetMenuItemInfo(hParentMenu, itemID, byPosition, &itemInfo);
2569 }
2570 }
2571
2572 // Note: static method
listBoxResetContent(HWND hWnd)2573 void CUIWindow::listBoxResetContent(HWND hWnd)
2574 {
2575 SendMessage(hWnd, LB_RESETCONTENT, 0, 0);
2576 }
2577
2578 // Note: static method
listBoxGetText(HWND hWnd,int index,ucstring & text)2579 void CUIWindow::listBoxGetText(HWND hWnd, int index, ucstring &text)
2580 {
2581 LRESULT getLengthResult = SendMessage(hWnd, LB_GETTEXTLEN,
2582 (WPARAM)index, 0);
2583 if (getLengthResult > 0 && getLengthResult != LB_ERR)
2584 {
2585 text.resize(getLengthResult);
2586 SendMessage(hWnd, LB_GETTEXT, (WPARAM)index, (LPARAM)&text[0]);
2587 }
2588 else
2589 {
2590 text.clear();
2591 }
2592 }
2593
2594 // Note: static method
listBoxSelectString(HWND hWnd,CUCSTR text)2595 void CUIWindow::listBoxSelectString(HWND hWnd, CUCSTR text)
2596 {
2597 SendMessage(hWnd, LB_SELECTSTRING, 0, (LPARAM)text);
2598 }
2599
2600 // Note: static method
listBoxSelectString(HWND hWnd,const ucstring & text)2601 void CUIWindow::listBoxSelectString(HWND hWnd, const ucstring &text)
2602 {
2603 listBoxSelectString(hWnd, text.c_str());
2604 }
2605
2606 // Note: static method
listBoxFindStringExact(HWND hWnd,CUCSTR text)2607 int CUIWindow::listBoxFindStringExact(HWND hWnd, CUCSTR text)
2608 {
2609 return (int)SendMessage(hWnd, LB_FINDSTRINGEXACT, 0, (LPARAM)text);
2610 }
2611
2612 // Note: static method
listBoxFindStringExact(HWND hWnd,const ucstring & text)2613 int CUIWindow::listBoxFindStringExact(HWND hWnd, const ucstring &text)
2614 {
2615 return listBoxFindStringExact(hWnd, text.c_str());
2616 }
2617
2618 // Note: static method
listBoxSetCurSel(HWND hWnd,int index)2619 void CUIWindow::listBoxSetCurSel(HWND hWnd, int index)
2620 {
2621 SendMessage(hWnd, LB_SETCURSEL, (WPARAM)index, 0);
2622 }
2623
2624 // Note: static method
listBoxGetCurSel(HWND hWnd)2625 int CUIWindow::listBoxGetCurSel(HWND hWnd)
2626 {
2627 return (int)SendMessage(hWnd, LB_GETCURSEL, 0, 0);
2628 }
2629
2630 // Note: static method
listBoxGetCount(HWND hWnd)2631 int CUIWindow::listBoxGetCount(HWND hWnd)
2632 {
2633 return (int)SendMessage(hWnd, LB_GETCOUNT, 0, 0);
2634 }
2635
2636 // Note: static method
listBoxAddString(HWND hWnd,CUCSTR text)2637 int CUIWindow::listBoxAddString(HWND hWnd, CUCSTR text)
2638 {
2639 return (int)SendMessage(hWnd, LB_ADDSTRING, 0, (LPARAM)text);
2640 }
2641
2642 // Note: static method
listBoxAddString(HWND hWnd,const ucstring & text)2643 int CUIWindow::listBoxAddString(HWND hWnd, const ucstring &text)
2644 {
2645 return listBoxAddString(hWnd, text.c_str());
2646 }
2647
2648 // Note: static method
buttonSetCheck(HWND hWnd,int state)2649 void CUIWindow::buttonSetCheck(HWND hWnd, int state)
2650 {
2651 SendMessage(hWnd, BM_SETCHECK, (WPARAM)state, 0);
2652 }
2653
2654 // Note: static method
buttonSetChecked(HWND hWnd,bool checked)2655 void CUIWindow::buttonSetChecked(HWND hWnd, bool checked)
2656 {
2657 buttonSetCheck(hWnd, checked ? BST_CHECKED : BST_UNCHECKED);
2658 }
2659
2660 // Note: static method
buttonGetCheck(HWND hWnd)2661 int CUIWindow::buttonGetCheck(HWND hWnd)
2662 {
2663 return (int)SendMessage(hWnd, BM_GETCHECK, 0, 0);
2664 }
2665
2666 // Note: static method
buttonIsChecked(HWND hWnd)2667 bool CUIWindow::buttonIsChecked(HWND hWnd)
2668 {
2669 return buttonGetCheck(hWnd) == BST_CHECKED;
2670 }
2671
2672 // Note: static method
buttonSetBitmap(HWND hWnd,HBITMAP hBitmap)2673 HBITMAP CUIWindow::buttonSetBitmap(HWND hWnd, HBITMAP hBitmap)
2674 {
2675 return (HBITMAP)SendMessage(hWnd, BM_SETIMAGE, IMAGE_BITMAP,
2676 (LPARAM)hBitmap);
2677 }
2678
2679 // Note: static method
buttonSetIcon(HWND hWnd,HICON hIcon)2680 HICON CUIWindow::buttonSetIcon(HWND hWnd, HICON hIcon)
2681 {
2682 return (HICON)SendMessage(hWnd, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
2683 }
2684
2685 // Note: static method
buttonGetBitmap(HWND hWnd)2686 HBITMAP CUIWindow::buttonGetBitmap(HWND hWnd)
2687 {
2688 return (HBITMAP)SendMessage(hWnd, BM_GETIMAGE, IMAGE_BITMAP, 0);
2689 }
2690
2691 // Note: static method
buttonGetIcon(HWND hWnd)2692 HICON CUIWindow::buttonGetIcon(HWND hWnd)
2693 {
2694 return (HICON)SendMessage(hWnd, BM_GETIMAGE, IMAGE_ICON, 0);
2695 }
2696
2697 // Note: static method
buttonSetStyle(HWND hWnd,DWORD dwStyle,bool redraw)2698 void CUIWindow::buttonSetStyle(HWND hWnd, DWORD dwStyle, bool redraw)
2699 {
2700 SendMessage(hWnd, BM_SETSTYLE, LOWORD(dwStyle),
2701 redraw ? MAKELPARAM(TRUE, 0) : 0);
2702 }
2703
2704 // Note: static method
progressBarSetPos(HWND hWnd,int pos)2705 int CUIWindow::progressBarSetPos(HWND hWnd, int pos)
2706 {
2707 return (int)SendMessage(hWnd, PBM_SETPOS, (WPARAM)pos, 0);
2708 }
2709
2710 // Note: static method
progressBarGetPos(HWND hWnd)2711 int CUIWindow::progressBarGetPos(HWND hWnd)
2712 {
2713 return (int)SendMessage(hWnd, PBM_GETPOS, 0, 0);
2714 }
2715
2716 // Note: static method
trackBarGetPos(HWND hWnd)2717 int CUIWindow::trackBarGetPos(HWND hWnd)
2718 {
2719 return (int)SendMessage(hWnd, TBM_GETPOS, 0, 0);
2720 }
2721
2722 // Note: static method
listBoxInsertString(HWND hWnd,int index,CUCSTR text)2723 void CUIWindow::listBoxInsertString(HWND hWnd, int index, CUCSTR text)
2724 {
2725 SendMessage(hWnd, LB_INSERTSTRING, (WPARAM)index, (LPARAM)text);
2726 }
2727
2728 // Note: static method
listBoxInsertString(HWND hWnd,int index,const ucstring & text)2729 void CUIWindow::listBoxInsertString(HWND hWnd, int index, const ucstring &text)
2730 {
2731 listBoxInsertString(hWnd, index, text.c_str());
2732 }
2733
2734 // Note: static method
listBoxDeleteString(HWND hWnd,int index)2735 void CUIWindow::listBoxDeleteString(HWND hWnd, int index)
2736 {
2737 SendMessage(hWnd, LB_DELETESTRING, (WPARAM)index, 0);
2738 }
2739
2740 // Note: static method
windowSetText(HWND hWnd,CUCSTR text)2741 void CUIWindow::windowSetText(HWND hWnd, CUCSTR text)
2742 {
2743 SendMessage(hWnd, WM_SETTEXT, 0, (LPARAM)text);
2744 }
2745
2746 // Note: static method
windowSetText(HWND hWnd,const ucstring & text)2747 void CUIWindow::windowSetText(HWND hWnd, const ucstring &text)
2748 {
2749 windowSetText(hWnd, text.c_str());
2750 }
2751
2752 // Note: static method
windowGetText(HWND hWnd,ucstring & text)2753 void CUIWindow::windowGetText(HWND hWnd, ucstring &text)
2754 {
2755 text.resize(SendMessage(hWnd, WM_GETTEXTLENGTH, 0, 0));
2756 sendMessageUC(hWnd, WM_GETTEXT, (WPARAM)text.size() + 1, (LPARAM)&text[0]);
2757 }
2758
2759 // Note: static method
windowGetValue(HWND hWnd,long & value)2760 bool CUIWindow::windowGetValue(HWND hWnd, long &value)
2761 {
2762 ucstring text;
2763
2764 windowGetText(hWnd, text);
2765 return sucscanf(text.c_str(), _UC("%ld"), &value) == 1;
2766 }
2767
2768 // Note: static method
windowGetValue(HWND hWnd,int & value)2769 bool CUIWindow::windowGetValue(HWND hWnd, int &value)
2770 {
2771 ucstring text;
2772
2773 windowGetText(hWnd, text);
2774 return sucscanf(text.c_str(), _UC("%d"), &value) == 1;
2775 }
2776
2777 // Note: static method
windowGetValue(HWND hWnd,float & value)2778 bool CUIWindow::windowGetValue(HWND hWnd, float &value)
2779 {
2780 ucstring text;
2781
2782 windowGetText(hWnd, text);
2783 return sucscanf(text.c_str(), _UC("%f"), &value) == 1;
2784 }
2785
2786 // Note: static method
windowGetValue(HWND hWnd,double & value)2787 bool CUIWindow::windowGetValue(HWND hWnd, double &value)
2788 {
2789 ucstring text;
2790
2791 windowGetText(hWnd, text);
2792 return sucscanf(text.c_str(), _UC("%lf"), &value) == 1;
2793 }
2794
2795 // Note: static method
checkGet(HWND hWnd)2796 bool CUIWindow::checkGet(HWND hWnd)
2797 {
2798 return SendMessage(hWnd, BM_GETCHECK, 0, 0) != 0;
2799 }
2800
2801 // Note: static method
checkSet(HWND hWnd,bool value)2802 void CUIWindow::checkSet(HWND hWnd, bool value)
2803 {
2804 SendMessage(hWnd, BM_SETCHECK, value, 0);
2805 }
2806
positionResizeGrip(HWND hSizeGrip)2807 void CUIWindow::positionResizeGrip(HWND hSizeGrip)
2808 {
2809 RECT clientRect;
2810 GetClientRect(hWindow, &clientRect);
2811 positionResizeGrip(hSizeGrip, clientRect.right, clientRect.bottom);
2812 RedrawWindow(hWindow, NULL, NULL, RDW_ERASE | RDW_INVALIDATE);
2813 }
2814
positionResizeGrip(HWND hSizeGrip,int parentWidth,int parentHeight)2815 void CUIWindow::positionResizeGrip(
2816 HWND hSizeGrip,
2817 int parentWidth,
2818 int parentHeight)
2819 {
2820 int sbSize = GetSystemMetrics(SM_CXVSCROLL);
2821
2822 MoveWindow(hSizeGrip, parentWidth - sbSize, parentHeight - sbSize, sbSize,
2823 sbSize, FALSE);
2824 }
2825
writeAutosaveInfo(int saveX,int saveY,int saveWidth,int saveHeight,int saveMaximized)2826 void CUIWindow::writeAutosaveInfo(
2827 int saveX,
2828 int saveY,
2829 int saveWidth,
2830 int saveHeight,
2831 int saveMaximized)
2832 {
2833 if (autosaveName != NULL)
2834 {
2835 char info[1024];
2836 float width, height;
2837 float scaleFactor = (float)getScaleFactor();
2838
2839 width = saveWidth / scaleFactor;
2840 height = saveHeight / scaleFactor;
2841 sprintf(info, "%d %d %f %f %d", saveX, saveY, width, height,
2842 saveMaximized);
2843 TCUserDefaults::setStringForKey(info, autosaveName, false);
2844 }
2845 }
2846
readAutosaveInfo(int & saveX,int & saveY,int & saveWidth,int & saveHeight,int & saveMaximized)2847 bool CUIWindow::readAutosaveInfo(
2848 int &saveX,
2849 int &saveY,
2850 int &saveWidth,
2851 int &saveHeight,
2852 int &saveMaximized)
2853 {
2854 bool retValue = false;
2855
2856 if (autosaveName != NULL)
2857 {
2858 char *info = TCUserDefaults::stringForKey(autosaveName, NULL, false);
2859
2860 if (info != NULL)
2861 {
2862 float width, height;
2863 if (sscanf(info, "%d %d %f %f %d", &saveX, &saveY, &width, &height,
2864 &saveMaximized) == 5)
2865 {
2866 saveWidth = scalePoints(width);
2867 saveHeight = scalePoints(height);
2868 retValue = true;
2869 }
2870 delete info;
2871 }
2872 }
2873 return retValue;
2874 }
2875
setAutosaveName(const char * value)2876 void CUIWindow::setAutosaveName(const char *value)
2877 {
2878 int saveX, saveY, saveWidth, saveHeight, saveMaximized;
2879
2880 autosaveName = new char[strlen(value) + 32];
2881 sprintf(autosaveName, "WindowAutosave/%s", value);
2882 if (readAutosaveInfo(saveX, saveY, saveWidth, saveHeight,
2883 saveMaximized))
2884 {
2885 RECT testRect = { 0, 0, 10, 10 };
2886 int adjustWidth;
2887 int adjustHeight;
2888 bool resizable = (GetWindowLong(hWindow, GWL_STYLE) &
2889 (WS_THICKFRAME | WS_MAXIMIZEBOX)) != 0;
2890
2891 AdjustWindowRectEx(&testRect, GetWindowLong(hWindow, GWL_STYLE), FALSE,
2892 GetWindowLong(hWindow, GWL_EXSTYLE));
2893 adjustWidth = testRect.right - testRect.left - 10;
2894 adjustHeight = testRect.bottom - testRect.top - 10;
2895 if (!resizable)
2896 {
2897 // If the window isn't resizable, don't try to restore its last size, in
2898 // case the size in the .rc file changes in a future version.
2899 RECT oldRect;
2900 GetWindowRect(hWindow, &oldRect);
2901 saveWidth = oldRect.right - oldRect.left;
2902 saveHeight = oldRect.bottom - oldRect.top;
2903 }
2904 if (saveWidth < minWidth + adjustWidth)
2905 {
2906 saveWidth = minWidth + adjustWidth;
2907 }
2908 if (saveHeight < minHeight + adjustHeight)
2909 {
2910 saveHeight = minHeight + adjustHeight;
2911 }
2912 RECT newRect = { saveX, saveY, saveX + saveWidth, saveY + saveHeight };
2913 HMONITOR hMonitor = MonitorFromRect(&newRect, MONITOR_DEFAULTTONULL);
2914 bool okRect = true;
2915 if (hMonitor == NULL)
2916 {
2917 // There is no longer a monitor where the window was last displayed.
2918 okRect = false;
2919 }
2920 else
2921 {
2922 MONITORINFO monitorInfo;
2923 memset(&monitorInfo, 0, sizeof(monitorInfo));
2924 monitorInfo.cbSize = sizeof(MONITORINFO);
2925 if (GetMonitorInfo(hMonitor, &monitorInfo))
2926 {
2927 RECT visibleRect;
2928 IntersectRect(&visibleRect, &newRect, &monitorInfo.rcWork);
2929 int totalArea = (newRect.right - newRect.left) *
2930 (newRect.bottom - newRect.top);
2931 int visibleArea = (visibleRect.right - visibleRect.left) *
2932 (visibleRect.bottom - visibleRect.top);
2933 if (visibleArea * 2 < totalArea)
2934 {
2935 // Less than half the window is visible.
2936 okRect = false;
2937 }
2938 }
2939 else
2940 {
2941 // We shouldn't get here; I think it means that the monitor that
2942 // was originally found for the rect went away between when we
2943 // asked for the rect's monitor and when we asked for info about
2944 // that monitor.
2945 okRect = false;
2946 }
2947 }
2948 if (!okRect)
2949 {
2950 // The saved window rect is less than half visible.
2951 // Use the saved window size, but use the default location.
2952 GetWindowRect(hWindow, &newRect);
2953 saveX = newRect.left;
2954 saveY = newRect.top;
2955 }
2956 MoveWindow(hWindow, saveX, saveY, saveWidth, saveHeight,
2957 saveMaximized == 0);
2958 if (saveMaximized)
2959 {
2960 ShowWindow(hWindow, SW_MAXIMIZE);
2961 }
2962 }
2963 }
2964
2965 #ifndef TC_NO_UNICODE
2966 // Note: static method
addFileType(char * fileTypes,const char * description,const char * filter)2967 void CUIWindow::addFileType(
2968 char *fileTypes,
2969 const char *description,
2970 const char *filter)
2971 {
2972 char* spot = fileTypes;
2973
2974 for (spot = fileTypes; spot[0] != 0 || spot[1] != 0; spot++)
2975 ;
2976 if (spot != fileTypes)
2977 {
2978 spot++;
2979 }
2980 strcpy(spot, description);
2981 spot += strlen(description) + 1;
2982 strcpy(spot, filter);
2983 spot += strlen(filter) + 1;
2984 *spot = 0;
2985 }
2986 #endif // TC_NO_UNICODE
2987
2988 // Note: static method
addFileType(UCSTR fileTypes,CUCSTR description,CUCSTR filter)2989 void CUIWindow::addFileType(
2990 UCSTR fileTypes,
2991 CUCSTR description,
2992 CUCSTR filter)
2993 {
2994 UCSTR spot = fileTypes;
2995
2996 for (spot = fileTypes; spot[0] != 0 || spot[1] != 0; spot++)
2997 ;
2998 if (spot != fileTypes)
2999 {
3000 spot++;
3001 }
3002 ucstrcpy(spot, description);
3003 spot += ucstrlen(description) + 1;
3004 ucstrcpy(spot, filter);
3005 spot += ucstrlen(filter) + 1;
3006 *spot = 0;
3007 }
3008
3009 // Note: static method
getOpenFilenameSize(bool uc)3010 int CUIWindow::getOpenFilenameSize(bool uc)
3011 {
3012 OSVERSIONINFO osvi;
3013
3014 osvi.dwOSVersionInfoSize = sizeof(osvi);
3015 #pragma warning(push)
3016 #pragma warning(disable:4996)
3017 GetVersionEx(&osvi);
3018 #pragma warning(pop)
3019 if (osvi.dwMajorVersion < 5)
3020 {
3021 if (uc)
3022 {
3023 return sizeof(OPENFILENAME_NT4UC);
3024 }
3025 else
3026 {
3027 return sizeof(OPENFILENAME_NT4A);
3028 }
3029 }
3030 else
3031 {
3032 if (uc)
3033 {
3034 return sizeof(OPENFILENAMEUC);
3035 }
3036 else
3037 {
3038 return sizeof(OPENFILENAMEA);
3039 }
3040 }
3041 }
3042
3043 // Note: static method
comboAddString(HWND hWnd,CUCSTR string)3044 int CUIWindow::comboAddString(HWND hWnd, CUCSTR string)
3045 {
3046 return (int)SendMessage(hWnd, CB_ADDSTRING, 0, (LPARAM)string);
3047 }
3048
3049 // Note: static method
comboAddString(HWND hWnd,const ucstring & string)3050 int CUIWindow::comboAddString(HWND hWnd, const ucstring &string)
3051 {
3052 return comboAddString(hWnd, string.c_str());
3053 }
3054
3055 // Note: static method
comboDeleteString(HWND hWnd,int index)3056 int CUIWindow::comboDeleteString(HWND hWnd, int index)
3057 {
3058 return (int)SendMessage(hWnd, CB_DELETESTRING, (WPARAM)index, 0);
3059 }
3060
3061 // Note: static method
comboSelectString(HWND hWnd,int startIndex,CUCSTR string)3062 int CUIWindow::comboSelectString(HWND hWnd, int startIndex, CUCSTR string)
3063 {
3064 return (int)SendMessage(hWnd, CB_SELECTSTRING, (WPARAM)startIndex,
3065 (LPARAM)string);
3066 }
3067
3068 // Note: static method
comboSelectString(HWND hWnd,int startIndex,const ucstring & string)3069 int CUIWindow::comboSelectString(
3070 HWND hWnd,
3071 int startIndex,
3072 const ucstring &string)
3073 {
3074 return comboSelectString(hWnd, startIndex, string.c_str());
3075 }
3076
3077 // Note: static method
comboResetContent(HWND hWnd)3078 void CUIWindow::comboResetContent(HWND hWnd)
3079 {
3080 SendMessage(hWnd, CB_RESETCONTENT, 0, 0);
3081 }
3082
3083 // Note: static method
comboSetCurSel(HWND hWnd,int index)3084 int CUIWindow::comboSetCurSel(HWND hWnd, int index)
3085 {
3086 return (int)SendMessage(hWnd, CB_SETCURSEL, (WPARAM)index, 0);
3087 }
3088
3089 // Note: static method
comboGetCurSel(HWND hWnd)3090 int CUIWindow::comboGetCurSel(HWND hWnd)
3091 {
3092 return (int)SendMessage(hWnd, CB_GETCURSEL, 0, 0);
3093 }
3094
3095 // Note: static method
comboGetCount(HWND hWnd)3096 int CUIWindow::comboGetCount(HWND hWnd)
3097 {
3098 return (int)SendMessage(hWnd, CB_GETCOUNT, 0, 0);
3099 }
3100
3101 // Note: static method
notificationName(UINT code)3102 const std::string CUIWindow::notificationName(UINT code)
3103 {
3104 static char buf[128];
3105
3106 switch (code)
3107 {
3108 case TBN_GETBUTTONINFOA:
3109 return "TBN_GETBUTTONINFOA";
3110 case TBN_BEGINDRAG:
3111 return "TBN_BEGINDRAG";
3112 case TBN_ENDDRAG:
3113 return "TBN_ENDDRAG";
3114 case TBN_BEGINADJUST:
3115 return "TBN_BEGINADJUST";
3116 case TBN_ENDADJUST:
3117 return "TBN_ENDADJUST";
3118 case TBN_RESET:
3119 return "TBN_RESET";
3120 case TBN_QUERYINSERT:
3121 return "TBN_QUERYINSERT";
3122 case TBN_QUERYDELETE:
3123 return "TBN_QUERYDELETE";
3124 case TBN_TOOLBARCHANGE:
3125 return "TBN_TOOLBARCHANGE";
3126 case TBN_CUSTHELP:
3127 return "TBN_CUSTHELP";
3128 case TBN_DROPDOWN:
3129 return "TBN_DROPDOWN";
3130 case TBN_GETOBJECT:
3131 return "TBN_GETOBJECT";
3132 case TBN_HOTITEMCHANGE:
3133 return "TBN_HOTITEMCHANGE";
3134 case TBN_DRAGOUT:
3135 return "TBN_DRAGOUT";
3136 case TBN_DELETINGBUTTON:
3137 return "TBN_DELETINGBUTTON";
3138 case TBN_GETDISPINFOA:
3139 return "TBN_GETDISPINFOA";
3140 case TBN_GETDISPINFOW:
3141 return "TBN_GETDISPINFOW";
3142 case TBN_GETINFOTIPA:
3143 return "TBN_GETINFOTIPA";
3144 case TBN_GETINFOTIPW:
3145 return "TBN_GETINFOTIPW";
3146 case TBN_GETBUTTONINFOW:
3147 return "TBN_GETBUTTONINFOW";
3148 case TBN_RESTORE:
3149 return "TBN_RESTORE";
3150 case TBN_SAVE:
3151 return "TBN_SAVE";
3152 case TBN_INITCUSTOMIZE:
3153 return "TBN_INITCUSTOMIZE";
3154
3155 case TTN_GETDISPINFOA:
3156 return "TTN_GETDISPINFOA";
3157 case TTN_GETDISPINFOW:
3158 return "TTN_GETDISPINFOW";
3159 case TTN_SHOW:
3160 return "TTN_SHOW";
3161 case TTN_POP:
3162 return "TTN_POP";
3163 case TTN_LINKCLICK:
3164 return "TTN_LINKCLICK";
3165
3166 case NM_OUTOFMEMORY:
3167 return "NM_OUTOFMEMORY";
3168 case NM_CLICK:
3169 return "NM_CLICK";
3170 case NM_DBLCLK:
3171 return "NM_DBLCLK";
3172 case NM_RETURN:
3173 return "NM_RETURN";
3174 case NM_RCLICK:
3175 return "NM_RCLICK";
3176 case NM_RDBLCLK:
3177 return "NM_RDBLCLK";
3178 case NM_SETFOCUS:
3179 return "NM_SETFOCUS";
3180 case NM_KILLFOCUS:
3181 return "NM_KILLFOCUS";
3182 case NM_CUSTOMDRAW:
3183 return "NM_CUSTOMDRAW";
3184 case NM_HOVER:
3185 return "NM_HOVER";
3186 case NM_NCHITTEST:
3187 return "NM_NCHITTEST";
3188 case NM_KEYDOWN:
3189 return "NM_KEYDOWN";
3190 case NM_RELEASEDCAPTURE:
3191 return "NM_RELEASEDCAPTURE";
3192 case NM_SETCURSOR:
3193 return "NM_SETCURSOR";
3194 case NM_CHAR:
3195 return "NM_CHAR";
3196 case NM_TOOLTIPSCREATED:
3197 return "NM_TOOLTIPSCREATED";
3198 case NM_LDOWN:
3199 return "NM_LDOWN";
3200 case NM_RDOWN:
3201 return "NM_RDOWN";
3202 case NM_THEMECHANGED:
3203 return "NM_THEMECHANGED";
3204 default:
3205 sprintf(buf, "0x%08X", code);
3206 return buf;
3207 }
3208 }
3209
createDIBSection(HDC hBitmapDC,int bitmapWidth,int bitmapHeight,BYTE ** bmBuffer,bool force32)3210 HBITMAP CUIWindow::createDIBSection(
3211 HDC hBitmapDC,
3212 int bitmapWidth,
3213 int bitmapHeight,
3214 BYTE **bmBuffer,
3215 bool force32 /*= false*/)
3216 {
3217 return TCImage::createDIBSection(hBitmapDC, bitmapWidth, bitmapHeight, bmBuffer, force32);
3218 }
3219
getScaleFactor(bool recalculate,UINT * dpiX,UINT * dpiY)3220 double CUIWindow::getScaleFactor(
3221 bool recalculate /*= false*/,
3222 UINT *dpiX /*= NULL*/,
3223 UINT *dpiY /*= NULL*/)
3224 {
3225 initScaler();
3226 return scaler->getScaleFactor(recalculate, dpiX, dpiY);
3227 }
3228
getBitmapSize(HBITMAP hBitmap,SIZE & size)3229 bool CUIWindow::getBitmapSize(HBITMAP hBitmap, SIZE& size)
3230 {
3231 BITMAP bm;
3232 if (GetObject(hBitmap, sizeof(BITMAP), &bm) != 0)
3233 {
3234 size.cx = bm.bmWidth;
3235 size.cy = bm.bmHeight;
3236 return true;
3237 }
3238 return false;
3239 }
3240
initScaler(void)3241 void CUIWindow::initScaler(void)
3242 {
3243 if (scaler == NULL)
3244 {
3245 scaler = new CUIScaler(this);
3246 }
3247 }
3248
scalePoints(int points)3249 int CUIWindow::scalePoints(int points)
3250 {
3251 initScaler();
3252 return scaler->scale(points);
3253 }
3254
unscalePixels(int pixels)3255 int CUIWindow::unscalePixels(int pixels)
3256 {
3257 initScaler();
3258 return scaler->unscale(pixels);
3259 }
3260
statusBarSetParts(HWND hStatusBar,WPARAM numParts,int * parts,bool scale)3261 bool CUIWindow::statusBarSetParts(
3262 HWND hStatusBar,
3263 WPARAM numParts,
3264 int *parts,
3265 bool scale /*= true*/)
3266 {
3267 if (scale)
3268 {
3269 for (WPARAM i = 0; i < numParts; ++i)
3270 {
3271 if (parts[i] != -1)
3272 {
3273 parts[i] = scalePoints(parts[i]);
3274 }
3275 }
3276 }
3277 return SendMessage(hStatusBar, SB_SETPARTS, numParts, (LPARAM)parts) !=
3278 FALSE;
3279 }
3280
3281 // Note: static method
statusBarGetText(HWND hWnd,TCByte part,ucstring & text)3282 WORD CUIWindow::statusBarGetText(HWND hWnd, TCByte part, ucstring &text)
3283 {
3284 LRESULT getLengthResult = SendMessage(hWnd, SB_GETTEXTLENGTH, part, 0);
3285 WORD length = LOWORD(getLengthResult);
3286 if (length > 0)
3287 {
3288 text.resize(length);
3289 return HIWORD(SendMessage(hWnd, SB_GETTEXT, part, (LPARAM)&text[0]));
3290 }
3291 else
3292 {
3293 text.clear();
3294 return HIWORD(getLengthResult);
3295 }
3296 }
3297
3298 // Note: static method
statusBarSetText(HWND hWnd,TCByte part,CUCSTR text,WORD flags)3299 bool CUIWindow::statusBarSetText(
3300 HWND hWnd,
3301 TCByte part,
3302 CUCSTR text,
3303 WORD flags)
3304 {
3305 return SendMessage(hWnd, SB_SETTEXT, part | flags, (LPARAM)text) != FALSE;
3306 }
3307
3308 // Note: static method
statusBarSetText(HWND hWnd,TCByte part,const ucstring & text,WORD flags)3309 bool CUIWindow::statusBarSetText(
3310 HWND hWnd,
3311 TCByte part,
3312 const ucstring &text,
3313 WORD flags)
3314 {
3315 return statusBarSetText(hWnd, part, text.c_str(), flags);
3316 }
3317
3318 // Note: static method
statusBarSetTipText(HWND hWnd,TCByte part,CUCSTR text)3319 void CUIWindow::statusBarSetTipText(
3320 HWND hWnd,
3321 TCByte part,
3322 CUCSTR text)
3323 {
3324 SendMessage(hWnd, SB_SETTIPTEXT, part, (LPARAM)text);
3325 }
3326
3327 // Note: static method
statusBarSetTipText(HWND hWnd,TCByte part,const ucstring & text)3328 void CUIWindow::statusBarSetTipText(
3329 HWND hWnd,
3330 TCByte part,
3331 const ucstring &text)
3332 {
3333 statusBarSetTipText(hWnd, part, text.c_str());
3334 }
3335
3336 // Note: static method
statusBarSetIcon(HWND hWnd,TCByte part,HICON hIcon)3337 bool CUIWindow::statusBarSetIcon(
3338 HWND hWnd,
3339 TCByte part,
3340 HICON hIcon)
3341 {
3342 return SendMessage(hWnd, SB_SETICON, part, (LPARAM)hIcon) != FALSE;
3343 }
3344
addImageToImageList(HIMAGELIST hImageList,int resourceId,const SIZE & size,double scaleFactor)3345 int CUIWindow::addImageToImageList(
3346 HIMAGELIST hImageList,
3347 int resourceId,
3348 const SIZE& size,
3349 double scaleFactor /*= 1.0*/)
3350 {
3351 TCImage *image = TCImage::createFromResource(NULL, resourceId, 4, true, scaleFactor);
3352 int retValue = addImageToImageList(hImageList, image, size);
3353 TCObject::release(image);
3354 return retValue;
3355 }
3356
addImageToImageList(HIMAGELIST hImageList,TCImage * image,const SIZE & size)3357 int CUIWindow::addImageToImageList(HIMAGELIST hImageList, TCImage *image, const SIZE& size)
3358 {
3359 if (image == NULL)
3360 {
3361 return -1;
3362 }
3363 int imageIndex = -1;
3364 HBITMAP hBitmap;
3365 HBITMAP hMask;
3366 bool stretched = false;
3367
3368 image->getBmpAndMask(hBitmap, hMask, false, CUIScaler::use32bit());
3369 if (image->getWidth() != size.cx || image->getHeight() != size.cy)
3370 {
3371 HBITMAP hScaleBitmap = NULL;
3372 HBITMAP hScaleMask = NULL;
3373 if (scaler->scaleBitmap(hBitmap, hScaleBitmap,
3374 (double)size.cx / (double)image->getWidth()) &&
3375 (hMask == NULL || scaler->scaleBitmap(hMask, hScaleMask)))
3376 {
3377 imageIndex = ImageList_Add(hImageList, hScaleBitmap, hScaleMask);
3378 stretched = true;
3379 }
3380 if (hScaleBitmap != NULL)
3381 {
3382 DeleteObject(hScaleBitmap);
3383 }
3384 if (hScaleMask != NULL)
3385 {
3386 DeleteObject(hScaleMask);
3387 }
3388 }
3389 if (!stretched)
3390 {
3391 imageIndex = ImageList_Add(hImageList, hBitmap, hMask);
3392 }
3393 if (hBitmap != NULL)
3394 {
3395 DeleteObject(hBitmap);
3396 }
3397 if (hMask != NULL)
3398 {
3399 DeleteObject(hMask);
3400 }
3401 return imageIndex;
3402 }
3403
setMinSize(int width,int height,bool unscale)3404 void CUIWindow::setMinSize(int width, int height, bool unscale)
3405 {
3406 if (unscale && width != -1)
3407 {
3408 minWidth = unscalePixels(width);
3409 }
3410 else
3411 {
3412 minWidth = width;
3413 }
3414 if (unscale && height != -1)
3415 {
3416 minHeight = unscalePixels(height);
3417 }
3418 else
3419 {
3420 minHeight = height;
3421 }
3422 }
3423
3424 // This calculates the height necessary in order to display a string of text in
3425 // a check button of a given width. If the button has a theme, the theme system
3426 // is used for the calculation. Otherwise, it's done manually.
calcCheckHeight(HWND hCheck,HDC hdc,int checkBoxWidth,int width,int & optimalWidth)3427 int CUIWindow::calcCheckHeight(
3428 HWND hCheck,
3429 HDC hdc,
3430 int checkBoxWidth,
3431 int width,
3432 int &optimalWidth)
3433 {
3434 HTHEME hTheme = CUIThemes::getWindowTheme(hCheck);
3435 ucstring text;
3436 int height;
3437 int newWidth = 0;
3438
3439 CUIWindow::windowGetText(hCheck, text);
3440 if (hTheme == NULL)
3441 {
3442 // Do the calculation manually using the width available in the check
3443 // button for the text.
3444 height = calcTextHeight(hdc, text, width - checkBoxWidth, newWidth);
3445 // The actual total width of the button is the width of the text plus
3446 // the width of the check box.
3447 newWidth += checkBoxWidth;
3448 }
3449 else
3450 {
3451 // Give it plenty of vertical space for the text.
3452 RECT boundingRect = { 0, 0, width, 1024 };
3453 RECT textRect;
3454 SIZE boxSize;
3455 int state = CBS_CHECKEDNORMAL;
3456 #ifdef TC_NO_UNICODE
3457 std::wstring wText;
3458
3459 stringtowstring(wText, text);
3460 #else // TC_NO_UNICODE
3461 std::wstring &wText = text;
3462 #endif // TC_NO_UNICODE
3463 // Get the size of the check box.
3464 CUIThemes::getThemePartSize(hTheme, hdc, BP_CHECKBOX, state, NULL,
3465 TS_TRUE, &boxSize);
3466 HMONITOR hMonitor = MonitorFromWindow(hCheck, MONITOR_DEFAULTTOPRIMARY);
3467 double scaleFactor = CUIScaler::getScaleFactor(hMonitor);
3468 // The + 3 is for the space between the check box and the text. (This
3469 // was determined empirically, but works at both the standard font DPI
3470 // of 96 and the "large fonts" DPI of 120.
3471 boundingRect.left += boxSize.cx + (LONG)(3 * scaleFactor);
3472 // The following basically does exactly what we are trying to do in this
3473 // method. It calculates the width and height needed for the text
3474 // string to fit into the given bounding box, wrapping as needed.
3475 CUIThemes::getThemeTextExtent(hTheme, hdc, BP_CHECKBOX, state,
3476 wText.c_str(), -1, DT_LEFT | DT_WORDBREAK | DT_CALCRECT,
3477 &boundingRect, &textRect);
3478 height = textRect.bottom - textRect.top;
3479 newWidth = textRect.right;
3480 }
3481 if (newWidth > optimalWidth)
3482 {
3483 optimalWidth = newWidth;
3484 }
3485 return height;
3486 }
3487
3488 // This calculates the height necessary in order to display a string of text in
3489 // a given width. It also calculate the actual width needed, and if that is
3490 // greater than optimalWidth, it updates optimalWidth to match. If the text has
3491 // to be wrapped to multiple lines, this does that at spaces. If a word in the
3492 // text is too long to fit on one line, it wraps at whatever location is
3493 // necessary.
calcTextHeight(HDC hdc,const ucstring & text,int width,int & optimalWidth)3494 int CUIWindow::calcTextHeight(
3495 HDC hdc,
3496 const ucstring &text,
3497 int width,
3498 int &optimalWidth)
3499 {
3500 // remaining keeps track of all the text that hasn't yet been accounted for.
3501 ucstring remaining = text;
3502 int height = 0;
3503
3504 for (int i = 0; remaining.size() > 0; i++)
3505 {
3506 SIZE size;
3507 ucstring line = remaining;
3508
3509 // Start out with the size needed for the whole string.
3510 CUIWindow::getTextExtentPoint32UC(hdc, line.c_str(), (int)line.size(),
3511 &size);
3512 while (size.cx > width)
3513 {
3514 // If we get here, the string didn't fit in the given width. Pull
3515 // a word off the right and try again.
3516 size_t index = line.rfind(' ');
3517
3518 if (line.size() == 0)
3519 {
3520 // Nothing fit at all, so just bail to avoid an infinite loop.
3521 break;
3522 }
3523 if (index >= line.size())
3524 {
3525 // No spaces for split: chop off one character.
3526 index = line.size() - 1;
3527 }
3528 line = line.substr(0, index);
3529 // At this point, line has had one word removed from it (if it
3530 // contains any spaces, otherwise one character removed). See what
3531 // size is neccessary for that.
3532 CUIWindow::getTextExtentPoint32UC(hdc, line.c_str(),
3533 (int)line.size(), &size);
3534 }
3535 // When we get here, whatever is in line fits in the given width.
3536 if (line.size() > 0)
3537 {
3538 size_t j;
3539
3540 // Pull the contents of line out of remaining.
3541 remaining = remaining.substr(line.size());
3542 // Find the first non-space character in remaining.
3543 for (j = 0; isspace(remaining[j]); j++)
3544 {
3545 // Don't do anything.
3546 }
3547 if (j > 0)
3548 {
3549 // If there were spaces on the beginning of remaining, trim them
3550 // off.
3551 remaining = remaining.substr(j);
3552 }
3553 }
3554 else
3555 {
3556 // Nothing in remaining fit in the given width, so bail.
3557 remaining.resize(0);
3558 }
3559 // Increment height by the height of this line of text.
3560 height += size.cy;
3561 if (size.cx > optimalWidth)
3562 {
3563 // This line of text is wider than optimalWidth, so update
3564 // optimalWidth to match this width.
3565 optimalWidth = size.cx;
3566 }
3567 }
3568 // Return the calculated height for the text string.
3569 return height;
3570 }
3571
staticFixSize(HWND hChild,LPARAM lParam)3572 static BOOL CALLBACK staticFixSize(HWND hChild, LPARAM lParam)
3573 {
3574 CUIWindow::fixControlSize(hChild, (HDC)lParam);
3575 return TRUE;
3576 }
3577
fixControlSize(HWND hChild,HDC hdc,bool force)3578 void CUIWindow::fixControlSize(HWND hChild, HDC hdc, bool force)
3579 {
3580 bool skip = !force;
3581 if (skip)
3582 {
3583 UCCHAR className[1024];
3584 GetClassName(hChild, className, COUNT_OF(className));
3585 if (ucstrcmp(className, WC_BUTTON) == 0)
3586 {
3587 long buttonStyle = GetWindowLong(hChild, GWL_STYLE) & BS_TYPEMASK;
3588 if (buttonStyle == BS_AUTOCHECKBOX || buttonStyle == BS_CHECKBOX ||
3589 buttonStyle == BS_AUTORADIOBUTTON || buttonStyle == BS_RADIOBUTTON)
3590 {
3591 // Check box or radio button.
3592 skip = false;
3593 }
3594 }
3595 }
3596 if (!skip)
3597 {
3598 RECT rect;
3599 ucstring title;
3600 CUIWindow::windowGetText(hChild, title);
3601 POINT point = { 0, 0 };
3602 ClientToScreen(GetParent(hChild), &point);
3603 GetWindowRect(hChild, &rect);
3604 rect.left -= point.x;
3605 rect.right -= point.x;
3606 rect.top -= point.y;
3607 rect.bottom -= point.y;
3608 int width = rect.right - rect.left;
3609 int optimalWidth = 0;
3610 int height = CUIWindow::calcCheckHeight(hChild, hdc,
3611 g_checkBoxWidth, width * 2, optimalWidth);
3612 MoveWindow(hChild, rect.left, rect.top, optimalWidth,
3613 rect.bottom - rect.top, TRUE);
3614 }
3615 }
3616
fixControlSize(HWND hWnd)3617 void CUIWindow::fixControlSize(HWND hWnd)
3618 {
3619 HWND hDlg = GetParent(hWnd);
3620 HDC hdc = GetDC(hDlg);
3621 HFONT hNewFont = (HFONT)SendMessage(hDlg, WM_GETFONT, 0, 0);
3622 HFONT hOldFont = (HFONT)SelectObject(hdc, hNewFont);
3623 fixControlSize(hWnd, hdc, true);
3624 SelectObject(hdc, hOldFont);
3625 ReleaseDC(hDlg, hdc);
3626 }
3627
fixDialogSizes(HWND hDlg)3628 void CUIWindow::fixDialogSizes(HWND hDlg)
3629 {
3630 HDC hdc = GetDC(hDlg);
3631 HFONT hNewFont = (HFONT)SendMessage(hDlg, WM_GETFONT, 0, 0);
3632 HFONT hOldFont = (HFONT)SelectObject(hdc, hNewFont);
3633 SIZE size;
3634 GetTextExtentPoint32A(hdc, "X", 1, &size);
3635 HMONITOR hMonitor = MonitorFromWindow(hDlg, MONITOR_DEFAULTTOPRIMARY);
3636 double scaleFactor = CUIScaler::getScaleFactor(hMonitor);
3637 // The check box size is calculated based on the font height. The + 4 is
3638 // for the space between the box and the text.
3639 g_checkBoxWidth = size.cy + (LONG)(scaleFactor * 4);
3640 EnumChildWindows(hDlg, staticFixSize, (LPARAM)hdc);
3641 SelectObject(hdc, hOldFont);
3642 ReleaseDC(hDlg, hdc);
3643 }
3644
haveWindowsVersionOrLater(WORD wMajorVersion,WORD wMinorVersion)3645 static bool haveWindowsVersionOrLater(WORD wMajorVersion, WORD wMinorVersion)
3646 {
3647 OSVERSIONINFOEX osvi;
3648 DWORDLONG dwlConditionMask = 0;
3649 int op = VER_GREATER_EQUAL;
3650
3651 // Initialize the OSVERSIONINFOEX structure.
3652 ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
3653 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
3654 osvi.dwMajorVersion = wMajorVersion;
3655 osvi.dwMinorVersion = wMinorVersion;
3656 osvi.wServicePackMajor = 0;
3657 osvi.wServicePackMinor = 0;
3658
3659 // Initialize the condition mask.
3660 VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, op);
3661 VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, op);
3662 VER_SET_CONDITION(dwlConditionMask, VER_SERVICEPACKMAJOR, op);
3663 VER_SET_CONDITION(dwlConditionMask, VER_SERVICEPACKMINOR, op);
3664
3665 // Perform the test.
3666 return VerifyVersionInfo(
3667 &osvi,
3668 VER_MAJORVERSION | VER_MINORVERSION |
3669 VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
3670 dwlConditionMask) != FALSE;
3671 }
3672
haveWindowsXPOrLater(void)3673 bool haveWindowsXPOrLater(void)
3674 {
3675 return haveWindowsVersionOrLater(5, 1);
3676 }
3677
haveWindowsVistaOrLater(void)3678 bool haveWindowsVistaOrLater(void)
3679 {
3680 return haveWindowsVersionOrLater(6, 0);
3681 }
3682
haveWindows7OrLater(void)3683 bool haveWindows7OrLater(void)
3684 {
3685 // Yes, "Windows 7" is Windows Version 6.1.
3686 return haveWindowsVersionOrLater(6, 1);
3687 }
3688