3 * Copyright (C) 2001, 2002, 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS welcome/autorun application
22 * FILE: base/setup/welcome/welcome.c
23 * PROGRAMMERS: Eric Kohl
24 * Casper S. Hornstrup (chorns@users.sourceforge.net)
25 * Hermes Belusca-Maito
28 * This utility can be customized by using localized INI configuration files.
29 * The default strings are stored in the utility's resources.
43 #include <reactos/version.h>
47 #define LIGHT_BLUE RGB(214, 239, 247)
48 #define DARK_BLUE RGB(107, 123, 140)
50 #define TITLE_WIDTH 480
51 #define TITLE_HEIGHT 93
53 /* GLOBALS ******************************************************************/
55 TCHAR szFrameClass
[] = TEXT("WelcomeWindowClass");
61 HWND hWndDefaultTopic
= NULL
;
65 ULONG ulInnerWidth
= TITLE_WIDTH
;
66 ULONG ulInnerHeight
= (TITLE_WIDTH
* 3) / 4;
67 ULONG ulTitleHeight
= TITLE_HEIGHT
+ 3;
69 HBITMAP hTitleBitmap
= NULL
;
70 HBITMAP hDefaultTopicBitmap
= NULL
;
71 HWND hWndCloseButton
= NULL
;
72 HWND hWndCheckButton
= NULL
;
74 BOOL bDisplayCheckBox
= FALSE
; // FIXME: We should also repaint the OS version correctly!
75 BOOL bDisplayExitBtn
= TRUE
;
77 #define BUFFER_SIZE 1024
79 #define TOPIC_TITLE_LENGTH 80
80 #define TOPIC_DESC_LENGTH 1024
87 TCHAR szTitle
[TOPIC_TITLE_LENGTH
];
88 TCHAR szDesc
[TOPIC_DESC_LENGTH
];
92 DWORD dwNumberTopics
= 0;
93 PTOPIC
* pTopics
= NULL
;
95 TCHAR szDefaultTitle
[TOPIC_TITLE_LENGTH
];
96 TCHAR szDefaultDesc
[TOPIC_DESC_LENGTH
];
98 INT nTopic
= -1; // Active (focused) topic
99 INT nDefaultTopic
= -1; // Default selected topic
101 HFONT hFontTopicButton
;
102 HFONT hFontTopicTitle
;
103 HFONT hFontTopicDescription
;
104 HFONT hFontCheckButton
;
108 HBRUSH hbrRightPanel
;
118 MainWndProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
121 /* FUNCTIONS ****************************************************************/
123 INT
GetLocaleName(IN LCID Locale
, OUT LPTSTR lpLCData
, IN SIZE_T cchData
)
127 /* Try to retrieve the locale language name (LOCALE_SNAME is supported on Vista+) */
128 ret
= GetLocaleInfo(Locale
, LOCALE_SNAME
, lpLCData
, cchData
);
129 if (ret
|| (GetLastError() != ERROR_INVALID_FLAGS
))
133 * We failed because LOCALE_SNAME was unrecognized, so try to manually build
134 * a language name in the form xx-YY (WARNING: this method has its limitations).
136 ret
= GetLocaleInfo(Locale
, LOCALE_SISO639LANGNAME
, lpLCData
, cchData
);
140 lpLCData
+= (ret
- 1);
141 cchData
-= (ret
- 1);
145 /* Try to get the second part; we add the '-' separator only if we succeed */
146 ret2
= GetLocaleInfo(Locale
, LOCALE_SISO3166CTRYNAME
, lpLCData
+ 1, cchData
- 1);
149 ret
+= ret2
; // 'ret' already counts '-'.
156 VOID
TranslateEscapes(IN OUT LPTSTR lpString
)
158 LPTSTR pEscape
= NULL
; // Next backslash escape sequence.
160 while (lpString
&& *lpString
)
162 /* Find the next backslash escape sequence */
163 pEscape
= _tcschr(lpString
, _T('\\'));
167 /* Go past the escape backslash */
168 lpString
= pEscape
+ 1;
170 /* Find which sequence it is */
174 // *pEscape = _T('\0'); // Enable if one wants to convert \<NULL> into <NULL>.
175 // lpString = pEscape + 1; // Loop will stop at the next iteration.
178 case _T('n'): case _T('r'):
179 // case _T('\\'): // others?
180 // So far we only need to deal with the newlines.
182 if (*lpString
== _T('n'))
184 else if (*lpString
== _T('r'))
187 memmove(lpString
, lpString
+ 1, (_tcslen(lpString
+ 1) + 1) * sizeof(TCHAR
));
191 /* Unknown escape sequence, ignore it */
200 LoadLocalizedResourcesFromINI(LCID Locale
, LPTSTR lpResPath
)
204 TCHAR szBuffer
[LOCALE_NAME_MAX_LENGTH
];
205 TCHAR szIniPath
[MAX_PATH
];
206 LPTSTR lpszSections
= NULL
, lpszSection
= NULL
;
207 PTOPIC pTopic
, *pTopicsTmp
;
209 /* Retrieve the locale name (on which the INI file name is based) */
210 dwRet
= (DWORD
)GetLocaleName(Locale
, szBuffer
, ARRAYSIZE(szBuffer
));
213 /* Fall back to english (US) */
214 StringCchCopy(szBuffer
, ARRAYSIZE(szBuffer
), TEXT("en-US"));
217 /* Build the INI file name */
218 StringCchCopy(szIniPath
, ARRAYSIZE(szIniPath
), lpResPath
);
219 StringCchCat(szIniPath
, ARRAYSIZE(szIniPath
), TEXT("\\"));
220 StringCchCat(szIniPath
, ARRAYSIZE(szIniPath
), szBuffer
);
221 StringCchCat(szIniPath
, ARRAYSIZE(szIniPath
), TEXT(".ini"));
223 /* Verify that the file exists, otherwise fall back to english (US) */
224 if (GetFileAttributes(szIniPath
) == INVALID_FILE_ATTRIBUTES
)
226 StringCchCopy(szBuffer
, ARRAYSIZE(szBuffer
), TEXT("en-US"));
228 StringCchCopy(szIniPath
, ARRAYSIZE(szIniPath
), lpResPath
);
229 StringCchCat(szIniPath
, ARRAYSIZE(szIniPath
), TEXT("\\"));
230 StringCchCat(szIniPath
, ARRAYSIZE(szIniPath
), szBuffer
);
231 StringCchCat(szIniPath
, ARRAYSIZE(szIniPath
), TEXT(".ini"));
234 /* Verify that the file exists, otherwise fall back to internal (localized) resource */
235 if (GetFileAttributes(szIniPath
) == INVALID_FILE_ATTRIBUTES
)
236 return FALSE
; // TODO: For localized resource, see the general function.
238 /* Try to load the default localized strings */
239 GetPrivateProfileString(TEXT("Defaults"), TEXT("AppTitle"), TEXT("ReactOS Welcome") /* default */,
240 szAppTitle
, ARRAYSIZE(szAppTitle
), szIniPath
);
241 if (!GetPrivateProfileString(TEXT("Defaults"), TEXT("DefaultTopicTitle"), NULL
/* default */,
242 szDefaultTitle
, ARRAYSIZE(szDefaultTitle
), szIniPath
))
246 if (!GetPrivateProfileString(TEXT("Defaults"), TEXT("DefaultTopicDescription"), NULL
/* default */,
247 szDefaultDesc
, ARRAYSIZE(szDefaultDesc
), szIniPath
))
253 TranslateEscapes(szDefaultDesc
);
256 /* Allocate a buffer big enough to hold all the section names */
257 for (dwSize
= BUFFER_SIZE
; ; dwSize
+= BUFFER_SIZE
)
259 lpszSections
= HeapAlloc(GetProcessHeap(), 0, dwSize
* sizeof(TCHAR
));
261 return TRUE
; // FIXME!
262 dwRet
= GetPrivateProfileSectionNames(lpszSections
, dwSize
, szIniPath
);
263 if (dwRet
< dwSize
- 2)
265 HeapFree(GetProcessHeap(), 0, lpszSections
);
271 /* Loop over the sections and load the topics */
272 lpszSection
= lpszSections
;
273 for (; lpszSection
&& *lpszSection
; lpszSection
+= (_tcslen(lpszSection
) + 1))
275 if (_tcsnicmp(lpszSection
, TEXT("Topic"), 5) == 0)
277 /* Allocate (or reallocate) the list of topics */
279 pTopicsTmp
= HeapAlloc(GetProcessHeap(), 0, (dwNumberTopics
+ 1) * sizeof(*pTopics
));
281 pTopicsTmp
= HeapReAlloc(GetProcessHeap(), 0, pTopics
, (dwNumberTopics
+ 1) * sizeof(*pTopics
));
283 break; // Cannot reallocate more
284 pTopics
= pTopicsTmp
;
286 /* Allocate a new topic */
287 pTopic
= HeapAlloc(GetProcessHeap(), 0, sizeof(*pTopic
));
289 break; // Cannot reallocate more
290 pTopics
[dwNumberTopics
++] = pTopic
;
292 /* Retrieve the information */
293 if (!GetPrivateProfileString(lpszSection
, TEXT("Button"), NULL
/* default */,
294 pTopic
->szText
, ARRAYSIZE(pTopic
->szText
), szIniPath
))
298 if (!GetPrivateProfileString(lpszSection
, TEXT("Title"), NULL
/* default */,
299 pTopic
->szTitle
, ARRAYSIZE(pTopic
->szTitle
), szIniPath
))
301 *pTopic
->szTitle
= 0;
303 if (!GetPrivateProfileString(lpszSection
, TEXT("Description"), NULL
/* default */,
304 pTopic
->szDesc
, ARRAYSIZE(pTopic
->szDesc
), szIniPath
))
310 TranslateEscapes(pTopic
->szDesc
);
312 if (!GetPrivateProfileString(lpszSection
, TEXT("Action"), NULL
/* default */,
313 pTopic
->szAction
, ARRAYSIZE(pTopic
->szAction
), szIniPath
))
315 *pTopic
->szAction
= 0;
319 TranslateEscapes(pTopic
->szAction
);
324 HeapFree(GetProcessHeap(), 0, lpszSections
);
330 LoadLocalizedResources(LPTSTR lpResPath
)
332 #define MAX_NUMBER_INTERNAL_TOPICS 3
335 PTOPIC pTopic
, *pTopicsTmp
;
341 * First, try to load the default internal (localized) strings.
342 * They can be redefined by the localized INI files.
344 if (!LoadString(hInstance
, IDS_APPTITLE
, szAppTitle
, ARRAYSIZE(szAppTitle
)))
345 StringCchCopy(szAppTitle
, ARRAYSIZE(szAppTitle
), TEXT("ReactOS Welcome"));
346 if (!LoadString(hInstance
, IDS_DEFAULTTOPICTITLE
, szDefaultTitle
, ARRAYSIZE(szDefaultTitle
)))
348 if (!LoadString(hInstance
, IDS_DEFAULTTOPICDESC
, szDefaultDesc
, ARRAYSIZE(szDefaultDesc
)))
351 /* Try to load the resources from INI file */
352 if (*lpResPath
&& LoadLocalizedResourcesFromINI(LOCALE_USER_DEFAULT
, lpResPath
))
355 /* We failed, fall back to internal (localized) resource */
356 for (i
= 0; i
< MAX_NUMBER_INTERNAL_TOPICS
; ++i
)
358 /* Allocate (or reallocate) the list of topics */
360 pTopicsTmp
= HeapAlloc(GetProcessHeap(), 0, (dwNumberTopics
+ 1) * sizeof(*pTopics
));
362 pTopicsTmp
= HeapReAlloc(GetProcessHeap(), 0, pTopics
, (dwNumberTopics
+ 1) * sizeof(*pTopics
));
364 break; // Cannot reallocate more
365 pTopics
= pTopicsTmp
;
367 /* Allocate a new topic */
368 pTopic
= HeapAlloc(GetProcessHeap(), 0, sizeof(*pTopic
));
370 break; // Cannot reallocate more
371 pTopics
[dwNumberTopics
++] = pTopic
;
373 /* Retrieve the information */
374 if (!LoadString(hInstance
, IDS_TOPICBUTTON0
+ i
, pTopic
->szText
, ARRAYSIZE(pTopic
->szText
)))
376 if (!LoadString(hInstance
, IDS_TOPICTITLE0
+ i
, pTopic
->szTitle
, ARRAYSIZE(pTopic
->szTitle
)))
377 *pTopic
->szTitle
= 0;
378 if (!LoadString(hInstance
, IDS_TOPICDESC0
+ i
, pTopic
->szDesc
, ARRAYSIZE(pTopic
->szDesc
)))
380 if (!LoadString(hInstance
, IDS_TOPICACTION0
+ i
, pTopic
->szAction
, ARRAYSIZE(pTopic
->szAction
)))
381 *pTopic
->szAction
= 0;
393 while (dwNumberTopics
--)
395 if (pTopics
[dwNumberTopics
])
396 HeapFree(GetProcessHeap(), 0, pTopics
[dwNumberTopics
]);
398 HeapFree(GetProcessHeap(), 0, pTopics
);
404 LoadConfiguration(VOID
)
406 TCHAR szAppPath
[MAX_PATH
];
407 TCHAR szIniPath
[MAX_PATH
];
408 TCHAR szResPath
[MAX_PATH
];
410 /* Retrieve the full path to this application */
411 GetModuleFileName(NULL
, szAppPath
, ARRAYSIZE(szAppPath
));
414 LPTSTR lpFileName
= _tcsrchr(szAppPath
, _T('\\'));
421 /* Build the full INI file path name */
422 StringCchCopy(szIniPath
, ARRAYSIZE(szIniPath
), szAppPath
);
423 StringCchCat(szIniPath
, ARRAYSIZE(szIniPath
), TEXT("\\welcome.ini"));
425 /* Verify that the file exists, otherwise use the default configuration */
426 if (GetFileAttributes(szIniPath
) == INVALID_FILE_ATTRIBUTES
)
428 /* Use the default configuration and retrieve the default resources */
429 return LoadLocalizedResources(TEXT(""));
432 /* Load the settings from the INI configuration file */
433 bDisplayCheckBox
= !!GetPrivateProfileInt(TEXT("Welcome"), TEXT("DisplayCheckBox"), FALSE
/* default */, szIniPath
);
434 bDisplayExitBtn
= !!GetPrivateProfileInt(TEXT("Welcome"), TEXT("DisplayExitButton"), TRUE
/* default */, szIniPath
);
436 if (!GetPrivateProfileString(TEXT("Welcome"), TEXT("ResourceDir"), NULL
/* default */,
437 szResPath
, ARRAYSIZE(szResPath
), szIniPath
))
442 /* Set the current directory to the one of this application, and retrieve the resources */
443 SetCurrentDirectory(szAppPath
);
444 return LoadLocalizedResources(szResPath
);
449 ShowLastWin32Error(HWND hWnd
)
451 LPTSTR lpMessageBuffer
= NULL
;
452 DWORD dwError
= GetLastError();
454 if (dwError
== ERROR_SUCCESS
)
457 if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
|
458 FORMAT_MESSAGE_FROM_SYSTEM
|
459 FORMAT_MESSAGE_IGNORE_INSERTS
,
463 (LPTSTR
)&lpMessageBuffer
,
469 MessageBox(hWnd
, lpMessageBuffer
, szAppTitle
, MB_OK
| MB_ICONERROR
);
470 LocalFree(lpMessageBuffer
);
475 _tWinMain(HINSTANCE hInst
,
476 HINSTANCE hPrevInstance
,
487 DWORD dwStyle
= WS_OVERLAPPED
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
|
488 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
;
491 UNREFERENCED_PARAMETER(hPrevInstance
);
492 UNREFERENCED_PARAMETER(lpszCmdLine
);
494 switch (GetUserDefaultUILanguage())
496 case MAKELANGID(LANG_HEBREW
, SUBLANG_DEFAULT
):
497 SetProcessDefaultLayout(LAYOUT_RTL
);
507 hMainIcon
= LoadIcon(hInstance
, MAKEINTRESOURCE(IDI_MAIN
));
509 /* Register the window class */
510 wndclass
.cbSize
= sizeof(WNDCLASSEX
);
511 wndclass
.style
= CS_HREDRAW
| CS_VREDRAW
;
512 wndclass
.lpfnWndProc
= (WNDPROC
)MainWndProc
;
513 wndclass
.cbClsExtra
= 0;
514 wndclass
.cbWndExtra
= 0;
515 wndclass
.hInstance
= hInstance
;
516 wndclass
.hIcon
= hMainIcon
;
517 wndclass
.hIconSm
= NULL
;
518 wndclass
.hCursor
= LoadCursor(NULL
, IDC_ARROW
);
519 wndclass
.hbrBackground
= NULL
;
520 wndclass
.lpszMenuName
= NULL
;
521 wndclass
.lpszClassName
= szFrameClass
;
523 RegisterClassEx(&wndclass
);
525 hTitleBitmap
= LoadBitmap(hInstance
, MAKEINTRESOURCE(IDB_TITLEBITMAP
));
526 if (hTitleBitmap
!= NULL
)
528 GetObject(hTitleBitmap
, sizeof(BITMAP
), &BitmapInfo
);
529 ulInnerWidth
= BitmapInfo
.bmWidth
;
530 ulInnerHeight
= (ulInnerWidth
* 3) / 4;
531 ulTitleHeight
= BitmapInfo
.bmHeight
+ 3;
532 DeleteObject(hTitleBitmap
);
534 ulInnerHeight
-= GetSystemMetrics(SM_CYCAPTION
);
537 rcWindow
.bottom
= ulInnerHeight
- 1;
539 rcWindow
.right
= ulInnerWidth
- 1;
541 AdjustWindowRect(&rcWindow
, dwStyle
, FALSE
);
542 xWidth
= rcWindow
.right
- rcWindow
.left
;
543 yHeight
= rcWindow
.bottom
- rcWindow
.top
;
545 xPos
= (GetSystemMetrics(SM_CXSCREEN
) - xWidth
) / 2;
546 yPos
= (GetSystemMetrics(SM_CYSCREEN
) - yHeight
) / 2;
548 rcTitlePanel
.top
= 0;
549 rcTitlePanel
.bottom
= ulTitleHeight
;
550 rcTitlePanel
.left
= 0;
551 rcTitlePanel
.right
= ulInnerWidth
- 1;
553 rcLeftPanel
.top
= rcTitlePanel
.bottom
;
554 rcLeftPanel
.bottom
= ulInnerHeight
- 1;
555 rcLeftPanel
.left
= 0;
556 rcLeftPanel
.right
= ulInnerWidth
/ 3;
558 rcRightPanel
.top
= rcLeftPanel
.top
;
559 rcRightPanel
.bottom
= rcLeftPanel
.bottom
;
560 rcRightPanel
.left
= rcLeftPanel
.right
;
561 rcRightPanel
.right
= ulInnerWidth
- 1;
563 /* Load the configuration and the resources */
566 /* Create main window */
567 hWndMain
= CreateWindow(szFrameClass
,
579 hSystemMenu
= GetSystemMenu(hWndMain
, FALSE
);
582 RemoveMenu(hSystemMenu
, SC_SIZE
, MF_BYCOMMAND
);
583 RemoveMenu(hSystemMenu
, SC_MAXIMIZE
, MF_BYCOMMAND
);
586 ShowWindow(hWndMain
, nCmdShow
);
587 UpdateWindow(hWndMain
);
589 while (GetMessage(&msg
, NULL
, 0, 0) != FALSE
)
591 TranslateMessage(&msg
);
592 DispatchMessage(&msg
);
603 ButtonSubclassWndProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
607 if (uMsg
== WM_MOUSEMOVE
)
609 i
= GetWindowLongPtr(hWnd
, GWL_ID
);
614 InvalidateRect(hWndMain
, &rcRightPanel
, TRUE
);
618 return CallWindowProc(fnOldBtn
, hWnd
, uMsg
, wParam
, lParam
);
623 RunAction(INT nTopic
)
625 // TCHAR CurrentDir[MAX_PATH];
627 TCHAR AppName
[MAX_PATH
];
629 InvalidateRect(hWndMain
, NULL
, TRUE
);
634 // GetCurrentDirectory(ARRAYSIZE(CurrentDir), CurrentDir);
636 StringCchCopy(AppName
, ARRAYSIZE(AppName
), pTopics
[nTopic
]->szAction
);
640 if (!_tcsicmp(AppName
, TEXT("<exit>")))
643 if (!_tcsnicmp(AppName
, TEXT("<msg>"), 5))
645 MessageBox(hWndMain
, AppName
+ 5, TEXT("ReactOS"), MB_OK
| MB_TASKMODAL
);
649 if (_tcsicmp(AppName
, TEXT("explorer.exe")) == 0)
651 // StringCchCat(AppName, ARRAYSIZE(AppName), TEXT(" "));
652 // StringCchCat(AppName, ARRAYSIZE(AppName), CurrentDir);
653 _tcscpy(Parameters
, TEXT("\\"));
660 ShellExecute(NULL
, NULL
, AppName
, Parameters
, NULL
, SW_SHOWDEFAULT
);
667 SubclassButton(HWND hWnd
)
669 fnOldBtn
= (WNDPROC
)SetWindowLongPtr(hWnd
, GWL_WNDPROC
, (DWORD_PTR
)ButtonSubclassWndProc
);
674 GetButtonHeight(HDC hDC
,
683 rect
.right
= dwWidth
- 20;
687 hOldFont
= (HFONT
)SelectObject(hDC
, hFont
);
688 DrawText(hDC
, szText
, -1, &rect
, DT_TOP
| DT_CALCRECT
| DT_WORDBREAK
);
689 SelectObject(hDC
, hOldFont
);
691 return (rect
.bottom
-rect
.top
+ 14);
696 OnCreate(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
705 UNREFERENCED_PARAMETER(wParam
);
706 UNREFERENCED_PARAMETER(lParam
);
708 hbrLightBlue
= CreateSolidBrush(LIGHT_BLUE
);
709 hbrDarkBlue
= CreateSolidBrush(DARK_BLUE
);
710 hbrRightPanel
= CreateSolidBrush(RGB(255, 255, 255));
712 /* Topic title font */
713 hFontTopicTitle
= CreateFont(-18, 0, 0, 0, FW_NORMAL
,
722 /* Topic description font */
723 hFontTopicDescription
= CreateFont(-11, 0, 0, 0, FW_THIN
,
732 /* Topic button font */
733 hFontTopicButton
= CreateFont(-11, 0, 0, 0, FW_BOLD
,
742 /* Load title bitmap */
743 if (hTitleBitmap
!= NULL
)
744 hTitleBitmap
= LoadBitmap(hInstance
, MAKEINTRESOURCE(IDB_TITLEBITMAP
));
746 /* Load topic bitmaps */
747 hDefaultTopicBitmap
= LoadBitmap(hInstance
, MAKEINTRESOURCE(IDB_DEFAULTTOPICBITMAP
));
748 for (i
= 0; i
< dwNumberTopics
; i
++)
750 // FIXME: Not implemented yet!
751 // pTopics[i]->hBitmap = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TOPICBITMAP0 + i));
752 pTopics
[i
]->hBitmap
= NULL
;
755 ScreenDC
= GetWindowDC(hWnd
);
756 hdcMem
= CreateCompatibleDC(ScreenDC
);
757 ReleaseDC(hWnd
, ScreenDC
);
759 /* Load and create buttons */
760 dwTop
= rcLeftPanel
.top
;
761 for (i
= 0; i
< dwNumberTopics
; i
++)
763 if (*pTopics
[i
]->szText
)
765 dwHeight
= GetButtonHeight(hdcMem
,
768 rcLeftPanel
.right
- rcLeftPanel
.left
);
770 pTopics
[i
]->hWndButton
= CreateWindow(TEXT("BUTTON"),
772 WS_CHILDWINDOW
| WS_VISIBLE
| WS_TABSTOP
| BS_MULTILINE
| BS_OWNERDRAW
,
775 rcLeftPanel
.right
- rcLeftPanel
.left
,
781 hWndDefaultTopic
= pTopics
[i
]->hWndButton
;
783 SubclassButton(pTopics
[i
]->hWndButton
);
784 SendMessage(pTopics
[i
]->hWndButton
, WM_SETFONT
, (WPARAM
)hFontTopicButton
, MAKELPARAM(TRUE
, 0));
788 pTopics
[i
]->hWndButton
= NULL
;
794 /* Create "Exit" button */
797 nLength
= LoadString(hInstance
, IDS_CLOSETEXT
, szText
, ARRAYSIZE(szText
));
800 hWndCloseButton
= CreateWindow(TEXT("BUTTON"),
802 WS_VISIBLE
| WS_CHILD
| BS_FLAT
,
803 rcRightPanel
.right
- 10 - 57,
804 rcRightPanel
.bottom
- 10 - 21,
808 (HMENU
)IDC_CLOSEBUTTON
,
811 hWndDefaultTopic
= NULL
;
813 SendMessage(hWndCloseButton
, WM_SETFONT
, (WPARAM
)hFontTopicButton
, MAKELPARAM(TRUE
, 0));
817 hWndCloseButton
= NULL
;
821 /* Create checkbox */
822 if (bDisplayCheckBox
)
824 nLength
= LoadString(hInstance
, IDS_CHECKTEXT
, szText
, ARRAYSIZE(szText
));
827 hFontCheckButton
= CreateFont(-10, 0, 0, 0, FW_THIN
,
836 hWndCheckButton
= CreateWindow(TEXT("BUTTON"),
838 WS_VISIBLE
| WS_CHILD
| BS_AUTOCHECKBOX
/**/| BS_FLAT
/**/,
839 rcLeftPanel
.left
+ 8,
840 rcLeftPanel
.bottom
- 8 - 13,
841 rcLeftPanel
.right
- rcLeftPanel
.left
- 16,
844 (HMENU
)IDC_CHECKBUTTON
,
847 SendMessage(hWndCheckButton
, WM_SETFONT
, (WPARAM
)hFontCheckButton
, MAKELPARAM(TRUE
, 0));
851 hFontCheckButton
= NULL
;
852 hWndCheckButton
= NULL
;
861 OnCommand(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
863 UNREFERENCED_PARAMETER(lParam
);
865 if (LOWORD(wParam
) == IDC_CLOSEBUTTON
)
869 else if ((LOWORD(wParam
) < dwNumberTopics
))
871 if (RunAction(LOWORD(wParam
)) == FALSE
)
872 DestroyWindow(hWnd
); // Corresponds to a <exit> action.
880 PaintBanner(HDC hdc
, LPRECT rcPanel
)
886 hOldBitmap
= (HBITMAP
)SelectObject(hdcMem
, hTitleBitmap
);
890 rcPanel
->right
- rcPanel
->left
,
892 hdcMem
, 0, 0, SRCCOPY
);
893 SelectObject(hdcMem
, hOldBitmap
);
896 hOldBrush
= (HBRUSH
)SelectObject(hdc
, hbrDarkBlue
);
900 rcPanel
->right
- rcPanel
->left
,
904 SelectObject(hdc
, hOldBrush
);
909 OnPaint(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
915 HBITMAP hOldBitmap
= NULL
;
918 RECT rcTitle
, rcDescription
;
921 LPTSTR lpTitle
= NULL
, lpDesc
= NULL
;
923 UNREFERENCED_PARAMETER(wParam
);
924 UNREFERENCED_PARAMETER(lParam
);
926 hdc
= BeginPaint(hWnd
, &ps
);
929 PaintBanner(hdc
, &rcTitlePanel
);
932 hOldBrush
= (HBRUSH
)SelectObject(hdc
, hbrLightBlue
);
936 rcLeftPanel
.right
- rcLeftPanel
.left
,
937 rcLeftPanel
.bottom
- rcLeftPanel
.top
,
939 SelectObject(hdc
, hOldBrush
);
942 hOldBrush
= (HBRUSH
)SelectObject(hdc
, WHITE_BRUSH
);
946 rcRightPanel
.right
- rcRightPanel
.left
,
947 rcRightPanel
.bottom
- rcRightPanel
.top
,
949 SelectObject(hdc
, hOldBrush
);
951 /* Draw dark vertical line */
952 hPen
= CreatePen(PS_SOLID
, 0, DARK_BLUE
);
953 hOldPen
= (HPEN
)SelectObject(hdc
, hPen
);
954 MoveToEx(hdc
, rcRightPanel
.left
, rcRightPanel
.top
, NULL
);
955 LineTo(hdc
, rcRightPanel
.left
, rcRightPanel
.bottom
);
956 SelectObject(hdc
, hOldPen
);
959 /* Draw topic bitmap */
960 if ((nTopic
== -1) && (hDefaultTopicBitmap
!= NULL
))
962 GetObject(hDefaultTopicBitmap
, sizeof(BITMAP
), &bmpInfo
);
963 hOldBitmap
= (HBITMAP
)SelectObject(hdcMem
, hDefaultTopicBitmap
);
965 rcRightPanel
.right
- bmpInfo
.bmWidth
,
966 rcRightPanel
.bottom
- bmpInfo
.bmHeight
,
974 else if ((nTopic
!= -1) && (pTopics
[nTopic
]->hBitmap
!= NULL
))
976 GetObject(pTopics
[nTopic
]->hBitmap
, sizeof(BITMAP
), &bmpInfo
);
977 hOldBitmap
= (HBITMAP
)SelectObject(hdcMem
, pTopics
[nTopic
]->hBitmap
);
979 rcRightPanel
.right
- bmpInfo
.bmWidth
,
980 rcRightPanel
.bottom
- bmpInfo
.bmHeight
,
991 lpTitle
= szDefaultTitle
;
992 lpDesc
= szDefaultDesc
;
996 lpTitle
= pTopics
[nTopic
]->szTitle
;
997 lpDesc
= pTopics
[nTopic
]->szDesc
;
1000 SetBkMode(hdc
, TRANSPARENT
);
1002 /* Draw version information */
1003 _stprintf(version
, TEXT("ReactOS %d.%d.%d"),
1004 KERNEL_VERSION_MAJOR
,
1005 KERNEL_VERSION_MINOR
,
1006 KERNEL_VERSION_PATCH_LEVEL
);
1008 rcTitle
.left
= rcLeftPanel
.left
+ 8;
1009 rcTitle
.right
= rcLeftPanel
.right
- 5;
1010 rcTitle
.top
= rcLeftPanel
.bottom
- 40;
1011 rcTitle
.bottom
= rcLeftPanel
.bottom
- 5;
1012 hOldFont
= (HFONT
)SelectObject(hdc
, hFontTopicDescription
);
1013 DrawText(hdc
, version
, -1, &rcTitle
, DT_BOTTOM
| DT_CALCRECT
| DT_SINGLELINE
);
1014 DrawText(hdc
, version
, -1, &rcTitle
, DT_BOTTOM
| DT_SINGLELINE
);
1015 SelectObject(hdc
, hOldFont
);
1017 /* Draw topic title */
1018 rcTitle
.left
= rcRightPanel
.left
+ 12;
1019 rcTitle
.right
= rcRightPanel
.right
- 8;
1020 rcTitle
.top
= rcRightPanel
.top
+ 8;
1021 rcTitle
.bottom
= rcTitle
.top
+ 57;
1022 hOldFont
= (HFONT
)SelectObject(hdc
, hFontTopicTitle
);
1023 DrawText(hdc
, lpTitle
, -1, &rcTitle
, DT_TOP
| DT_CALCRECT
);
1025 SetTextColor(hdc
, DARK_BLUE
);
1026 DrawText(hdc
, lpTitle
, -1, &rcTitle
, DT_TOP
);
1028 /* Draw topic description */
1029 rcDescription
.left
= rcRightPanel
.left
+ 12;
1030 rcDescription
.right
= rcRightPanel
.right
- 8;
1031 rcDescription
.top
= rcTitle
.bottom
+ 8;
1032 rcDescription
.bottom
= rcRightPanel
.bottom
- 20;
1034 SelectObject(hdc
, hFontTopicDescription
);
1035 SetTextColor(hdc
, RGB(0, 0, 0));
1036 DrawText(hdc
, lpDesc
, -1, &rcDescription
, DT_TOP
| DT_WORDBREAK
);
1038 SetBkMode(hdc
, OPAQUE
);
1039 SelectObject(hdc
, hOldFont
);
1041 SelectObject(hdcMem
, hOldBrush
);
1042 SelectObject(hdcMem
, hOldBitmap
);
1044 EndPaint(hWnd
, &ps
);
1051 OnDrawItem(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
1053 LPDRAWITEMSTRUCT lpDis
= (LPDRAWITEMSTRUCT
)lParam
;
1059 UNREFERENCED_PARAMETER(hWnd
);
1060 UNREFERENCED_PARAMETER(wParam
);
1062 if (lpDis
->hwndItem
== hWndCloseButton
)
1064 DrawFrameControl(lpDis
->hDC
,
1067 DFCS_BUTTONPUSH
| DFCS_FLAT
);
1071 if (lpDis
->CtlID
== (ULONG
)nTopic
)
1072 hOldBrush
= (HBRUSH
)SelectObject(lpDis
->hDC
, hbrRightPanel
);
1074 hOldBrush
= (HBRUSH
)SelectObject(lpDis
->hDC
, hbrLightBlue
);
1079 lpDis
->rcItem
.right
,
1080 lpDis
->rcItem
.bottom
,
1082 SelectObject(lpDis
->hDC
, hOldBrush
);
1084 hPen
= CreatePen(PS_SOLID
, 0, DARK_BLUE
);
1085 hOldPen
= (HPEN
)SelectObject(lpDis
->hDC
, hPen
);
1086 MoveToEx(lpDis
->hDC
, lpDis
->rcItem
.left
, lpDis
->rcItem
.bottom
- 1, NULL
);
1087 LineTo(lpDis
->hDC
, lpDis
->rcItem
.right
, lpDis
->rcItem
.bottom
- 1);
1088 SelectObject(lpDis
->hDC
, hOldPen
);
1091 InflateRect(&lpDis
->rcItem
, -10, -4);
1092 OffsetRect(&lpDis
->rcItem
, 0, 1);
1093 GetWindowText(lpDis
->hwndItem
, szText
, ARRAYSIZE(szText
));
1094 SetTextColor(lpDis
->hDC
, RGB(0, 0, 0));
1095 iBkMode
= SetBkMode(lpDis
->hDC
, TRANSPARENT
);
1096 DrawText(lpDis
->hDC
, szText
, -1, &lpDis
->rcItem
, DT_TOP
| DT_LEFT
| DT_WORDBREAK
);
1097 SetBkMode(lpDis
->hDC
, iBkMode
);
1105 OnMouseMove(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
1107 UNREFERENCED_PARAMETER(wParam
);
1108 UNREFERENCED_PARAMETER(lParam
);
1114 InvalidateRect(hWndMain
, &rcRightPanel
, TRUE
);
1122 OnCtlColorStatic(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
1124 UNREFERENCED_PARAMETER(hWnd
);
1126 if ((HWND
)lParam
== hWndCheckButton
)
1128 SetBkColor((HDC
)wParam
, LIGHT_BLUE
);
1129 return (LRESULT
)hbrLightBlue
;
1137 OnActivate(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
1139 UNREFERENCED_PARAMETER(hWnd
);
1140 UNREFERENCED_PARAMETER(wParam
);
1141 UNREFERENCED_PARAMETER(lParam
);
1144 InvalidateRect(hWndMain
, &rcRightPanel
, TRUE
);
1150 OnDestroy(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
1154 UNREFERENCED_PARAMETER(hWnd
);
1155 UNREFERENCED_PARAMETER(wParam
);
1156 UNREFERENCED_PARAMETER(lParam
);
1158 for (i
= 0; i
< dwNumberTopics
; i
++)
1160 if (pTopics
[i
]->hWndButton
!= NULL
)
1161 DestroyWindow(pTopics
[i
]->hWndButton
);
1164 if (hWndCloseButton
!= NULL
)
1165 DestroyWindow(hWndCloseButton
);
1167 if (hWndCheckButton
!= NULL
)
1168 DestroyWindow(hWndCheckButton
);
1172 /* Delete bitmaps */
1173 DeleteObject(hDefaultTopicBitmap
);
1174 DeleteObject(hTitleBitmap
);
1175 for (i
= 0; i
< dwNumberTopics
; i
++)
1177 if (pTopics
[i
]->hBitmap
!= NULL
)
1178 DeleteObject(pTopics
[i
]->hBitmap
);
1181 DeleteObject(hFontTopicTitle
);
1182 DeleteObject(hFontTopicDescription
);
1183 DeleteObject(hFontTopicButton
);
1185 if (hFontCheckButton
!= NULL
)
1186 DeleteObject(hFontCheckButton
);
1188 DeleteObject(hbrLightBlue
);
1189 DeleteObject(hbrDarkBlue
);
1190 DeleteObject(hbrRightPanel
);
1197 MainWndProc(HWND hWnd
,
1205 return OnCreate(hWnd
, wParam
, lParam
);
1208 return OnCommand(hWnd
, wParam
, lParam
);
1211 return OnActivate(hWnd
, wParam
, lParam
);
1214 return OnPaint(hWnd
, wParam
, lParam
);
1217 return OnDrawItem(hWnd
, wParam
, lParam
);
1219 case WM_CTLCOLORSTATIC
:
1220 return OnCtlColorStatic(hWnd
, wParam
, lParam
);
1223 return OnMouseMove(hWnd
, wParam
, lParam
);
1226 OnDestroy(hWnd
, wParam
, lParam
);
1231 return DefWindowProc(hWnd
, uMsg
, wParam
, lParam
);