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 LoadTopicsFromINI(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 if (!GetPrivateProfileString(TEXT("Defaults"), TEXT("DefaultTopicTitle"), NULL
/* default */,
240 szDefaultTitle
, ARRAYSIZE(szDefaultTitle
), szIniPath
))
244 if (!GetPrivateProfileString(TEXT("Defaults"), TEXT("DefaultTopicDescription"), NULL
/* default */,
245 szDefaultDesc
, ARRAYSIZE(szDefaultDesc
), szIniPath
))
251 TranslateEscapes(szDefaultDesc
);
254 /* Allocate a buffer big enough to hold all the section names */
255 for (dwSize
= BUFFER_SIZE
; ; dwSize
+= BUFFER_SIZE
)
257 lpszSections
= HeapAlloc(GetProcessHeap(), 0, dwSize
* sizeof(TCHAR
));
259 return TRUE
; // FIXME!
260 dwRet
= GetPrivateProfileSectionNames(lpszSections
, dwSize
, szIniPath
);
261 if (dwRet
< dwSize
- 2)
263 HeapFree(GetProcessHeap(), 0, lpszSections
);
269 /* Loop over the sections and load the topics */
270 lpszSection
= lpszSections
;
271 for (; lpszSection
&& *lpszSection
; lpszSection
+= (_tcslen(lpszSection
) + 1))
273 if (_tcsnicmp(lpszSection
, TEXT("Topic"), 5) == 0)
275 /* Allocate (or reallocate) the list of topics */
277 pTopicsTmp
= HeapAlloc(GetProcessHeap(), 0, (dwNumberTopics
+ 1) * sizeof(*pTopics
));
279 pTopicsTmp
= HeapReAlloc(GetProcessHeap(), 0, pTopics
, (dwNumberTopics
+ 1) * sizeof(*pTopics
));
281 break; // Cannot reallocate more
282 pTopics
= pTopicsTmp
;
284 /* Allocate a new topic */
285 pTopic
= HeapAlloc(GetProcessHeap(), 0, sizeof(*pTopic
));
287 break; // Cannot reallocate more
288 pTopics
[dwNumberTopics
++] = pTopic
;
290 /* Retrieve the information */
291 if (!GetPrivateProfileString(lpszSection
, TEXT("Button"), NULL
/* default */,
292 pTopic
->szText
, ARRAYSIZE(pTopic
->szText
), szIniPath
))
296 if (!GetPrivateProfileString(lpszSection
, TEXT("Title"), NULL
/* default */,
297 pTopic
->szTitle
, ARRAYSIZE(pTopic
->szTitle
), szIniPath
))
299 *pTopic
->szTitle
= 0;
301 if (!GetPrivateProfileString(lpszSection
, TEXT("Description"), NULL
/* default */,
302 pTopic
->szDesc
, ARRAYSIZE(pTopic
->szDesc
), szIniPath
))
308 TranslateEscapes(pTopic
->szDesc
);
310 if (!GetPrivateProfileString(lpszSection
, TEXT("Action"), NULL
/* default */,
311 pTopic
->szAction
, ARRAYSIZE(pTopic
->szAction
), szIniPath
))
313 *pTopic
->szAction
= 0;
317 TranslateEscapes(pTopic
->szAction
);
322 HeapFree(GetProcessHeap(), 0, lpszSections
);
328 LoadTopics(LPTSTR lpResPath
)
330 #define MAX_NUMBER_INTERNAL_TOPICS 3
333 PTOPIC pTopic
, *pTopicsTmp
;
339 * First, try to load the default internal (localized) strings.
340 * They can be redefined by the localized INI files.
342 if (!LoadString(hInstance
, IDS_DEFAULTTOPICTITLE
, szDefaultTitle
, ARRAYSIZE(szDefaultTitle
)))
344 if (!LoadString(hInstance
, IDS_DEFAULTTOPICDESC
, szDefaultDesc
, ARRAYSIZE(szDefaultDesc
)))
347 /* Try to load the topics from INI file */
348 if (*lpResPath
&& LoadTopicsFromINI(LOCALE_USER_DEFAULT
, lpResPath
))
351 /* We failed, fall back to internal (localized) resource */
352 for (i
= 0; i
< MAX_NUMBER_INTERNAL_TOPICS
; ++i
)
354 /* Allocate (or reallocate) the list of topics */
356 pTopicsTmp
= HeapAlloc(GetProcessHeap(), 0, (dwNumberTopics
+ 1) * sizeof(*pTopics
));
358 pTopicsTmp
= HeapReAlloc(GetProcessHeap(), 0, pTopics
, (dwNumberTopics
+ 1) * sizeof(*pTopics
));
360 break; // Cannot reallocate more
361 pTopics
= pTopicsTmp
;
363 /* Allocate a new topic */
364 pTopic
= HeapAlloc(GetProcessHeap(), 0, sizeof(*pTopic
));
366 break; // Cannot reallocate more
367 pTopics
[dwNumberTopics
++] = pTopic
;
369 /* Retrieve the information */
370 if (!LoadString(hInstance
, IDS_TOPICBUTTON0
+ i
, pTopic
->szText
, ARRAYSIZE(pTopic
->szText
)))
372 if (!LoadString(hInstance
, IDS_TOPICTITLE0
+ i
, pTopic
->szTitle
, ARRAYSIZE(pTopic
->szTitle
)))
373 *pTopic
->szTitle
= 0;
374 if (!LoadString(hInstance
, IDS_TOPICDESC0
+ i
, pTopic
->szDesc
, ARRAYSIZE(pTopic
->szDesc
)))
376 if (!LoadString(hInstance
, IDS_TOPICACTION0
+ i
, pTopic
->szAction
, ARRAYSIZE(pTopic
->szAction
)))
377 *pTopic
->szAction
= 0;
389 while (dwNumberTopics
--)
391 if (pTopics
[dwNumberTopics
])
392 HeapFree(GetProcessHeap(), 0, pTopics
[dwNumberTopics
]);
394 HeapFree(GetProcessHeap(), 0, pTopics
);
400 LoadConfiguration(VOID
)
402 TCHAR szAppPath
[MAX_PATH
];
403 TCHAR szIniPath
[MAX_PATH
];
404 TCHAR szResPath
[MAX_PATH
];
406 /* Retrieve the full path to this application */
407 GetModuleFileName(NULL
, szAppPath
, ARRAYSIZE(szAppPath
));
410 LPTSTR lpFileName
= _tcsrchr(szAppPath
, _T('\\'));
417 /* Build the full INI file path name */
418 StringCchCopy(szIniPath
, ARRAYSIZE(szIniPath
), szAppPath
);
419 StringCchCat(szIniPath
, ARRAYSIZE(szIniPath
), TEXT("\\welcome.ini"));
421 /* Verify that the file exists, otherwise use the default configuration */
422 if (GetFileAttributes(szIniPath
) == INVALID_FILE_ATTRIBUTES
)
424 /* Use the default configuration and retrieve the default topics */
425 return LoadTopics(TEXT(""));
428 /* Load the settings from the INI configuration file */
429 bDisplayCheckBox
= !!GetPrivateProfileInt(TEXT("Welcome"), TEXT("DisplayCheckBox"), FALSE
/* default */, szIniPath
);
430 bDisplayExitBtn
= !!GetPrivateProfileInt(TEXT("Welcome"), TEXT("DisplayExitButton"), TRUE
/* default */, szIniPath
);
432 if (!GetPrivateProfileString(TEXT("Welcome"), TEXT("ResourceDir"), NULL
/* default */,
433 szResPath
, ARRAYSIZE(szResPath
), szIniPath
))
438 /* Set the current directory to the one of this application, and retrieve the topics */
439 SetCurrentDirectory(szAppPath
);
440 return LoadTopics(szResPath
);
445 ShowLastWin32Error(HWND hWnd
)
447 LPTSTR lpMessageBuffer
= NULL
;
448 DWORD dwError
= GetLastError();
450 if (dwError
== ERROR_SUCCESS
)
453 if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
|
454 FORMAT_MESSAGE_FROM_SYSTEM
|
455 FORMAT_MESSAGE_IGNORE_INSERTS
,
459 (LPTSTR
)&lpMessageBuffer
,
465 MessageBox(hWnd
, lpMessageBuffer
, szAppTitle
, MB_OK
| MB_ICONERROR
);
466 LocalFree(lpMessageBuffer
);
471 _tWinMain(HINSTANCE hInst
,
472 HINSTANCE hPrevInstance
,
483 DWORD dwStyle
= WS_OVERLAPPED
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
|
484 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
;
487 UNREFERENCED_PARAMETER(hPrevInstance
);
488 UNREFERENCED_PARAMETER(lpszCmdLine
);
490 switch (GetUserDefaultUILanguage())
492 case MAKELANGID(LANG_HEBREW
, SUBLANG_DEFAULT
):
493 SetProcessDefaultLayout(LAYOUT_RTL
);
503 hMainIcon
= LoadIcon(hInstance
, MAKEINTRESOURCE(IDI_MAIN
));
505 /* Register the window class */
506 wndclass
.cbSize
= sizeof(WNDCLASSEX
);
507 wndclass
.style
= CS_HREDRAW
| CS_VREDRAW
;
508 wndclass
.lpfnWndProc
= (WNDPROC
)MainWndProc
;
509 wndclass
.cbClsExtra
= 0;
510 wndclass
.cbWndExtra
= 0;
511 wndclass
.hInstance
= hInstance
;
512 wndclass
.hIcon
= hMainIcon
;
513 wndclass
.hIconSm
= NULL
;
514 wndclass
.hCursor
= LoadCursor(NULL
, IDC_ARROW
);
515 wndclass
.hbrBackground
= NULL
;
516 wndclass
.lpszMenuName
= NULL
;
517 wndclass
.lpszClassName
= szFrameClass
;
519 RegisterClassEx(&wndclass
);
521 hTitleBitmap
= LoadBitmap(hInstance
, MAKEINTRESOURCE(IDB_TITLEBITMAP
));
522 if (hTitleBitmap
!= NULL
)
524 GetObject(hTitleBitmap
, sizeof(BITMAP
), &BitmapInfo
);
525 ulInnerWidth
= BitmapInfo
.bmWidth
;
526 ulInnerHeight
= (ulInnerWidth
* 3) / 4;
527 ulTitleHeight
= BitmapInfo
.bmHeight
+ 3;
528 DeleteObject(hTitleBitmap
);
530 ulInnerHeight
-= GetSystemMetrics(SM_CYCAPTION
);
533 rcWindow
.bottom
= ulInnerHeight
- 1;
535 rcWindow
.right
= ulInnerWidth
- 1;
537 AdjustWindowRect(&rcWindow
, dwStyle
, FALSE
);
538 xWidth
= rcWindow
.right
- rcWindow
.left
;
539 yHeight
= rcWindow
.bottom
- rcWindow
.top
;
541 xPos
= (GetSystemMetrics(SM_CXSCREEN
) - xWidth
) / 2;
542 yPos
= (GetSystemMetrics(SM_CYSCREEN
) - yHeight
) / 2;
544 rcTitlePanel
.top
= 0;
545 rcTitlePanel
.bottom
= ulTitleHeight
;
546 rcTitlePanel
.left
= 0;
547 rcTitlePanel
.right
= ulInnerWidth
- 1;
549 rcLeftPanel
.top
= rcTitlePanel
.bottom
;
550 rcLeftPanel
.bottom
= ulInnerHeight
- 1;
551 rcLeftPanel
.left
= 0;
552 rcLeftPanel
.right
= ulInnerWidth
/ 3;
554 rcRightPanel
.top
= rcLeftPanel
.top
;
555 rcRightPanel
.bottom
= rcLeftPanel
.bottom
;
556 rcRightPanel
.left
= rcLeftPanel
.right
;
557 rcRightPanel
.right
= ulInnerWidth
- 1;
559 if (!LoadString(hInstance
, IDS_APPTITLE
, szAppTitle
, ARRAYSIZE(szAppTitle
)))
560 StringCchCopy(szAppTitle
, ARRAYSIZE(szAppTitle
), TEXT("ReactOS Welcome"));
562 /* Load the configuration and the topics */
565 /* Create main window */
566 hWndMain
= CreateWindow(szFrameClass
,
578 hSystemMenu
= GetSystemMenu(hWndMain
, FALSE
);
581 RemoveMenu(hSystemMenu
, SC_SIZE
, MF_BYCOMMAND
);
582 RemoveMenu(hSystemMenu
, SC_MAXIMIZE
, MF_BYCOMMAND
);
585 ShowWindow(hWndMain
, nCmdShow
);
586 UpdateWindow(hWndMain
);
588 while (GetMessage(&msg
, NULL
, 0, 0) != FALSE
)
590 TranslateMessage(&msg
);
591 DispatchMessage(&msg
);
602 ButtonSubclassWndProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
606 if (uMsg
== WM_MOUSEMOVE
)
608 i
= GetWindowLongPtr(hWnd
, GWL_ID
);
613 InvalidateRect(hWndMain
, &rcRightPanel
, TRUE
);
617 return CallWindowProc(fnOldBtn
, hWnd
, uMsg
, wParam
, lParam
);
622 RunAction(INT nTopic
)
624 // TCHAR CurrentDir[MAX_PATH];
626 TCHAR AppName
[MAX_PATH
];
628 InvalidateRect(hWndMain
, NULL
, TRUE
);
633 // GetCurrentDirectory(ARRAYSIZE(CurrentDir), CurrentDir);
635 StringCchCopy(AppName
, ARRAYSIZE(AppName
), pTopics
[nTopic
]->szAction
);
639 if (!_tcsicmp(AppName
, TEXT("<exit>")))
642 if (!_tcsnicmp(AppName
, TEXT("<msg>"), 5))
644 MessageBox(hWndMain
, AppName
+ 5, TEXT("ReactOS"), MB_OK
| MB_TASKMODAL
);
648 if (_tcsicmp(AppName
, TEXT("explorer.exe")) == 0)
650 // StringCchCat(AppName, ARRAYSIZE(AppName), TEXT(" "));
651 // StringCchCat(AppName, ARRAYSIZE(AppName), CurrentDir);
652 _tcscpy(Parameters
, TEXT("\\"));
659 ShellExecute(NULL
, NULL
, AppName
, Parameters
, NULL
, SW_SHOWDEFAULT
);
666 SubclassButton(HWND hWnd
)
668 fnOldBtn
= (WNDPROC
)SetWindowLongPtr(hWnd
, GWL_WNDPROC
, (DWORD_PTR
)ButtonSubclassWndProc
);
673 GetButtonHeight(HDC hDC
,
682 rect
.right
= dwWidth
- 20;
686 hOldFont
= (HFONT
)SelectObject(hDC
, hFont
);
687 DrawText(hDC
, szText
, -1, &rect
, DT_TOP
| DT_CALCRECT
| DT_WORDBREAK
);
688 SelectObject(hDC
, hOldFont
);
690 return (rect
.bottom
-rect
.top
+ 14);
695 OnCreate(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
704 UNREFERENCED_PARAMETER(wParam
);
705 UNREFERENCED_PARAMETER(lParam
);
707 hbrLightBlue
= CreateSolidBrush(LIGHT_BLUE
);
708 hbrDarkBlue
= CreateSolidBrush(DARK_BLUE
);
709 hbrRightPanel
= CreateSolidBrush(RGB(255, 255, 255));
711 /* Topic title font */
712 hFontTopicTitle
= CreateFont(-18, 0, 0, 0, FW_NORMAL
,
721 /* Topic description font */
722 hFontTopicDescription
= CreateFont(-11, 0, 0, 0, FW_THIN
,
731 /* Topic button font */
732 hFontTopicButton
= CreateFont(-11, 0, 0, 0, FW_BOLD
,
741 /* Load title bitmap */
742 if (hTitleBitmap
!= NULL
)
743 hTitleBitmap
= LoadBitmap(hInstance
, MAKEINTRESOURCE(IDB_TITLEBITMAP
));
745 /* Load topic bitmaps */
746 hDefaultTopicBitmap
= LoadBitmap(hInstance
, MAKEINTRESOURCE(IDB_DEFAULTTOPICBITMAP
));
747 for (i
= 0; i
< dwNumberTopics
; i
++)
749 // FIXME: Not implemented yet!
750 // pTopics[i]->hBitmap = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TOPICBITMAP0 + i));
751 pTopics
[i
]->hBitmap
= NULL
;
754 ScreenDC
= GetWindowDC(hWnd
);
755 hdcMem
= CreateCompatibleDC(ScreenDC
);
756 ReleaseDC(hWnd
, ScreenDC
);
758 /* Load and create buttons */
759 dwTop
= rcLeftPanel
.top
;
760 for (i
= 0; i
< dwNumberTopics
; i
++)
762 if (*pTopics
[i
]->szText
)
764 dwHeight
= GetButtonHeight(hdcMem
,
767 rcLeftPanel
.right
- rcLeftPanel
.left
);
769 pTopics
[i
]->hWndButton
= CreateWindow(TEXT("BUTTON"),
771 WS_CHILDWINDOW
| WS_VISIBLE
| WS_TABSTOP
| BS_MULTILINE
| BS_OWNERDRAW
,
774 rcLeftPanel
.right
- rcLeftPanel
.left
,
780 hWndDefaultTopic
= pTopics
[i
]->hWndButton
;
782 SubclassButton(pTopics
[i
]->hWndButton
);
783 SendMessage(pTopics
[i
]->hWndButton
, WM_SETFONT
, (WPARAM
)hFontTopicButton
, MAKELPARAM(TRUE
, 0));
787 pTopics
[i
]->hWndButton
= NULL
;
793 /* Create "Exit" button */
796 nLength
= LoadString(hInstance
, IDS_CLOSETEXT
, szText
, ARRAYSIZE(szText
));
799 hWndCloseButton
= CreateWindow(TEXT("BUTTON"),
801 WS_VISIBLE
| WS_CHILD
| BS_FLAT
,
802 rcRightPanel
.right
- 10 - 57,
803 rcRightPanel
.bottom
- 10 - 21,
807 (HMENU
)IDC_CLOSEBUTTON
,
810 hWndDefaultTopic
= NULL
;
812 SendMessage(hWndCloseButton
, WM_SETFONT
, (WPARAM
)hFontTopicButton
, MAKELPARAM(TRUE
, 0));
816 hWndCloseButton
= NULL
;
820 /* Create checkbox */
821 if (bDisplayCheckBox
)
823 nLength
= LoadString(hInstance
, IDS_CHECKTEXT
, szText
, ARRAYSIZE(szText
));
826 hFontCheckButton
= CreateFont(-10, 0, 0, 0, FW_THIN
,
835 hWndCheckButton
= CreateWindow(TEXT("BUTTON"),
837 WS_VISIBLE
| WS_CHILD
| BS_AUTOCHECKBOX
/**/| BS_FLAT
/**/,
838 rcLeftPanel
.left
+ 8,
839 rcLeftPanel
.bottom
- 8 - 13,
840 rcLeftPanel
.right
- rcLeftPanel
.left
- 16,
843 (HMENU
)IDC_CHECKBUTTON
,
846 SendMessage(hWndCheckButton
, WM_SETFONT
, (WPARAM
)hFontCheckButton
, MAKELPARAM(TRUE
, 0));
850 hFontCheckButton
= NULL
;
851 hWndCheckButton
= NULL
;
860 OnCommand(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
862 UNREFERENCED_PARAMETER(lParam
);
864 if (LOWORD(wParam
) == IDC_CLOSEBUTTON
)
868 else if ((LOWORD(wParam
) < dwNumberTopics
))
870 if (RunAction(LOWORD(wParam
)) == FALSE
)
871 DestroyWindow(hWnd
); // Corresponds to a <exit> action.
879 PaintBanner(HDC hdc
, LPRECT rcPanel
)
885 hOldBitmap
= (HBITMAP
)SelectObject(hdcMem
, hTitleBitmap
);
889 rcPanel
->right
- rcPanel
->left
,
891 hdcMem
, 0, 0, SRCCOPY
);
892 SelectObject(hdcMem
, hOldBitmap
);
895 hOldBrush
= (HBRUSH
)SelectObject(hdc
, hbrDarkBlue
);
899 rcPanel
->right
- rcPanel
->left
,
903 SelectObject(hdc
, hOldBrush
);
908 OnPaint(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
914 HBITMAP hOldBitmap
= NULL
;
917 RECT rcTitle
, rcDescription
;
920 LPTSTR lpTitle
= NULL
, lpDesc
= NULL
;
922 UNREFERENCED_PARAMETER(wParam
);
923 UNREFERENCED_PARAMETER(lParam
);
925 hdc
= BeginPaint(hWnd
, &ps
);
928 PaintBanner(hdc
, &rcTitlePanel
);
931 hOldBrush
= (HBRUSH
)SelectObject(hdc
, hbrLightBlue
);
935 rcLeftPanel
.right
- rcLeftPanel
.left
,
936 rcLeftPanel
.bottom
- rcLeftPanel
.top
,
938 SelectObject(hdc
, hOldBrush
);
941 hOldBrush
= (HBRUSH
)SelectObject(hdc
, WHITE_BRUSH
);
945 rcRightPanel
.right
- rcRightPanel
.left
,
946 rcRightPanel
.bottom
- rcRightPanel
.top
,
948 SelectObject(hdc
, hOldBrush
);
950 /* Draw dark vertical line */
951 hPen
= CreatePen(PS_SOLID
, 0, DARK_BLUE
);
952 hOldPen
= (HPEN
)SelectObject(hdc
, hPen
);
953 MoveToEx(hdc
, rcRightPanel
.left
, rcRightPanel
.top
, NULL
);
954 LineTo(hdc
, rcRightPanel
.left
, rcRightPanel
.bottom
);
955 SelectObject(hdc
, hOldPen
);
958 /* Draw topic bitmap */
959 if ((nTopic
== -1) && (hDefaultTopicBitmap
!= NULL
))
961 GetObject(hDefaultTopicBitmap
, sizeof(BITMAP
), &bmpInfo
);
962 hOldBitmap
= (HBITMAP
)SelectObject(hdcMem
, hDefaultTopicBitmap
);
964 rcRightPanel
.right
- bmpInfo
.bmWidth
,
965 rcRightPanel
.bottom
- bmpInfo
.bmHeight
,
973 else if ((nTopic
!= -1) && (pTopics
[nTopic
]->hBitmap
!= NULL
))
975 GetObject(pTopics
[nTopic
]->hBitmap
, sizeof(BITMAP
), &bmpInfo
);
976 hOldBitmap
= (HBITMAP
)SelectObject(hdcMem
, pTopics
[nTopic
]->hBitmap
);
978 rcRightPanel
.right
- bmpInfo
.bmWidth
,
979 rcRightPanel
.bottom
- bmpInfo
.bmHeight
,
990 lpTitle
= szDefaultTitle
;
991 lpDesc
= szDefaultDesc
;
995 lpTitle
= pTopics
[nTopic
]->szTitle
;
996 lpDesc
= pTopics
[nTopic
]->szDesc
;
999 SetBkMode(hdc
, TRANSPARENT
);
1001 /* Draw version information */
1002 _stprintf(version
, TEXT("ReactOS %d.%d.%d"),
1003 KERNEL_VERSION_MAJOR
,
1004 KERNEL_VERSION_MINOR
,
1005 KERNEL_VERSION_PATCH_LEVEL
);
1007 rcTitle
.left
= rcLeftPanel
.left
+ 8;
1008 rcTitle
.right
= rcLeftPanel
.right
- 5;
1009 rcTitle
.top
= rcLeftPanel
.bottom
- 40;
1010 rcTitle
.bottom
= rcLeftPanel
.bottom
- 5;
1011 hOldFont
= (HFONT
)SelectObject(hdc
, hFontTopicDescription
);
1012 DrawText(hdc
, version
, -1, &rcTitle
, DT_BOTTOM
| DT_CALCRECT
| DT_SINGLELINE
);
1013 DrawText(hdc
, version
, -1, &rcTitle
, DT_BOTTOM
| DT_SINGLELINE
);
1014 SelectObject(hdc
, hOldFont
);
1016 /* Draw topic title */
1017 rcTitle
.left
= rcRightPanel
.left
+ 12;
1018 rcTitle
.right
= rcRightPanel
.right
- 8;
1019 rcTitle
.top
= rcRightPanel
.top
+ 8;
1020 rcTitle
.bottom
= rcTitle
.top
+ 57;
1021 hOldFont
= (HFONT
)SelectObject(hdc
, hFontTopicTitle
);
1022 DrawText(hdc
, lpTitle
, -1, &rcTitle
, DT_TOP
| DT_CALCRECT
);
1024 SetTextColor(hdc
, DARK_BLUE
);
1025 DrawText(hdc
, lpTitle
, -1, &rcTitle
, DT_TOP
);
1027 /* Draw topic description */
1028 rcDescription
.left
= rcRightPanel
.left
+ 12;
1029 rcDescription
.right
= rcRightPanel
.right
- 8;
1030 rcDescription
.top
= rcTitle
.bottom
+ 8;
1031 rcDescription
.bottom
= rcRightPanel
.bottom
- 20;
1033 SelectObject(hdc
, hFontTopicDescription
);
1034 SetTextColor(hdc
, RGB(0, 0, 0));
1035 DrawText(hdc
, lpDesc
, -1, &rcDescription
, DT_TOP
| DT_WORDBREAK
);
1037 SetBkMode(hdc
, OPAQUE
);
1038 SelectObject(hdc
, hOldFont
);
1040 SelectObject(hdcMem
, hOldBrush
);
1041 SelectObject(hdcMem
, hOldBitmap
);
1043 EndPaint(hWnd
, &ps
);
1050 OnDrawItem(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
1052 LPDRAWITEMSTRUCT lpDis
= (LPDRAWITEMSTRUCT
)lParam
;
1058 UNREFERENCED_PARAMETER(hWnd
);
1059 UNREFERENCED_PARAMETER(wParam
);
1061 if (lpDis
->hwndItem
== hWndCloseButton
)
1063 DrawFrameControl(lpDis
->hDC
,
1066 DFCS_BUTTONPUSH
| DFCS_FLAT
);
1070 if (lpDis
->CtlID
== (ULONG
)nTopic
)
1071 hOldBrush
= (HBRUSH
)SelectObject(lpDis
->hDC
, hbrRightPanel
);
1073 hOldBrush
= (HBRUSH
)SelectObject(lpDis
->hDC
, hbrLightBlue
);
1078 lpDis
->rcItem
.right
,
1079 lpDis
->rcItem
.bottom
,
1081 SelectObject(lpDis
->hDC
, hOldBrush
);
1083 hPen
= CreatePen(PS_SOLID
, 0, DARK_BLUE
);
1084 hOldPen
= (HPEN
)SelectObject(lpDis
->hDC
, hPen
);
1085 MoveToEx(lpDis
->hDC
, lpDis
->rcItem
.left
, lpDis
->rcItem
.bottom
- 1, NULL
);
1086 LineTo(lpDis
->hDC
, lpDis
->rcItem
.right
, lpDis
->rcItem
.bottom
- 1);
1087 SelectObject(lpDis
->hDC
, hOldPen
);
1090 InflateRect(&lpDis
->rcItem
, -10, -4);
1091 OffsetRect(&lpDis
->rcItem
, 0, 1);
1092 GetWindowText(lpDis
->hwndItem
, szText
, ARRAYSIZE(szText
));
1093 SetTextColor(lpDis
->hDC
, RGB(0, 0, 0));
1094 iBkMode
= SetBkMode(lpDis
->hDC
, TRANSPARENT
);
1095 DrawText(lpDis
->hDC
, szText
, -1, &lpDis
->rcItem
, DT_TOP
| DT_LEFT
| DT_WORDBREAK
);
1096 SetBkMode(lpDis
->hDC
, iBkMode
);
1104 OnMouseMove(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
1106 UNREFERENCED_PARAMETER(wParam
);
1107 UNREFERENCED_PARAMETER(lParam
);
1113 InvalidateRect(hWndMain
, &rcRightPanel
, TRUE
);
1121 OnCtlColorStatic(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
1123 UNREFERENCED_PARAMETER(hWnd
);
1125 if ((HWND
)lParam
== hWndCheckButton
)
1127 SetBkColor((HDC
)wParam
, LIGHT_BLUE
);
1128 return (LRESULT
)hbrLightBlue
;
1136 OnActivate(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
1138 UNREFERENCED_PARAMETER(hWnd
);
1139 UNREFERENCED_PARAMETER(wParam
);
1140 UNREFERENCED_PARAMETER(lParam
);
1143 InvalidateRect(hWndMain
, &rcRightPanel
, TRUE
);
1149 OnDestroy(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
1153 UNREFERENCED_PARAMETER(hWnd
);
1154 UNREFERENCED_PARAMETER(wParam
);
1155 UNREFERENCED_PARAMETER(lParam
);
1157 for (i
= 0; i
< dwNumberTopics
; i
++)
1159 if (pTopics
[i
]->hWndButton
!= NULL
)
1160 DestroyWindow(pTopics
[i
]->hWndButton
);
1163 if (hWndCloseButton
!= NULL
)
1164 DestroyWindow(hWndCloseButton
);
1166 if (hWndCheckButton
!= NULL
)
1167 DestroyWindow(hWndCheckButton
);
1171 /* Delete bitmaps */
1172 DeleteObject(hDefaultTopicBitmap
);
1173 DeleteObject(hTitleBitmap
);
1174 for (i
= 0; i
< dwNumberTopics
; i
++)
1176 if (pTopics
[i
]->hBitmap
!= NULL
)
1177 DeleteObject(pTopics
[i
]->hBitmap
);
1180 DeleteObject(hFontTopicTitle
);
1181 DeleteObject(hFontTopicDescription
);
1182 DeleteObject(hFontTopicButton
);
1184 if (hFontCheckButton
!= NULL
)
1185 DeleteObject(hFontCheckButton
);
1187 DeleteObject(hbrLightBlue
);
1188 DeleteObject(hbrDarkBlue
);
1189 DeleteObject(hbrRightPanel
);
1196 MainWndProc(HWND hWnd
,
1204 return OnCreate(hWnd
, wParam
, lParam
);
1207 return OnCommand(hWnd
, wParam
, lParam
);
1210 return OnActivate(hWnd
, wParam
, lParam
);
1213 return OnPaint(hWnd
, wParam
, lParam
);
1216 return OnDrawItem(hWnd
, wParam
, lParam
);
1218 case WM_CTLCOLORSTATIC
:
1219 return OnCtlColorStatic(hWnd
, wParam
, lParam
);
1222 return OnMouseMove(hWnd
, wParam
, lParam
);
1225 OnDestroy(hWnd
, wParam
, lParam
);
1230 return DefWindowProc(hWnd
, uMsg
, wParam
, lParam
);