Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1527 lines
44 KiB

  1. //////////////////////////////////////////////////////////////////////////
  2. //
  3. // dlgapp.cpp
  4. //
  5. // This file contains the main entry point into the application and
  6. // the implementation of the CDlgApp class.
  7. //
  8. // (C) Copyright 1997 by Microsoft Corporation. All rights reserved.
  9. //
  10. //////////////////////////////////////////////////////////////////////////
  11. #include <windows.h>
  12. #include <commctrl.h>
  13. #include <shlwapi.h> // for string compare functions
  14. #include <debug.h>
  15. #include <tchar.h>
  16. #include <winuser.h>
  17. #pragma hdrstop
  18. #include "dlgapp.h"
  19. #include "util.h"
  20. #include "resource.h"
  21. WNDPROC g_fnBtnProc; // the window proc for a button.
  22. #define LAUNCHTIMER 101
  23. #define WAITTIMER 102
  24. #define TEXT_TITLE 0
  25. #define TEXT_HEADER 1
  26. #define TEXT_BODY 2
  27. #define TEXT_SUB 3
  28. #define BUTTONTEXTGAP 5
  29. #define TRANSBUTTONGAP 10
  30. DWORD rgdwText[7][4] = {{IDS_TEXT0_TITLE, IDS_TEXT0_HEADER, IDS_TEXT0, IDS_TEXT0_SUB},
  31. {IDS_TEXT1_TITLE, IDS_TEXT1_HEADER, IDS_TEXT1, IDS_TEXT1_SUB},
  32. {IDS_TEXT2_TITLE, IDS_TEXT2_HEADER, IDS_TEXT2, IDS_TEXT2_SUB},
  33. {IDS_TEXT3_TITLE, IDS_TEXT3_HEADER, IDS_TEXT3, IDS_TEXT3_SUB},
  34. {IDS_TEXT4_TITLE, IDS_TEXT4_HEADER, IDS_TEXT4, IDS_TEXT4_SUB},
  35. {IDS_TEXT5_TITLE, IDS_TEXT5_HEADER, IDS_TEXT5, IDS_TEXT5_SUB},
  36. {IDS_TEXT6_TITLE, IDS_TEXT6_HEADER, IDS_TEXT6, IDS_TEXT6_SUB}};
  37. RECT rgrectText[4] = {{97, 18, 797, 98}, {120, 100, 750, 200}, {120, 200, 750, 450}, {120, 430, 750, 520}};
  38. RECT rgrectText640[4] = {{77, 28, 597, 98}, {50, 90, 620, 150}, {50, 160, 620, 350}, {50, 330, 620, 400}};
  39. DWORD rgdwLabel[] = {IDS_MENULABEL0, IDS_MENULABEL1, IDS_MENULABEL2, IDS_MENULABEL3, IDS_MENULABEL4, IDS_MENULABEL5, IDS_MENULABEL6}; // which text label for a menu item
  40. DWORD rgdwPosition[] = {4, 2, 3, 4, 0, 0, 1};
  41. #define EXIT_DEX 0
  42. #define BACK_DEX 1
  43. #define NEXT_DEX 2
  44. #define FINISH_DEX 3
  45. #define LINK_DEX 4
  46. #define RADIO_1_DEX 5
  47. #define RADIO_0_DEX 6
  48. #define EMPTY 99
  49. POINT rgPtIcons[] = {{150,320}, {150, 360}, {0, 537}, {0, 537}, {740, 537}};
  50. POINT rgPtIconText[] = {{180,320}, {180, 360}, {0, 537}, {0, 537}, {0, 537}};
  51. UINT cWidthIconText[] = {0, 0, 0, 0, 0};
  52. POINT rgPtIcons640[] = {{80,250}, {80, 280}, {0, 403}, {0, 403}, {600, 403}};
  53. POINT rgPtIconText640[] = {{110,250}, {110, 280}, {0, 403}, {0, 403}, {600, 403}};
  54. DWORD rgdwMenu[7][5] = {{EXIT_DEX},
  55. {EXIT_DEX, NEXT_DEX},
  56. {EXIT_DEX, BACK_DEX, NEXT_DEX, RADIO_1_DEX, RADIO_0_DEX},
  57. {EXIT_DEX, BACK_DEX, NEXT_DEX},
  58. {EXIT_DEX, BACK_DEX, NEXT_DEX},
  59. {FINISH_DEX, BACK_DEX, LINK_DEX},
  60. {EXIT_DEX}};
  61. DWORD rgdwMenuByPos[7][5] = {{EMPTY, EMPTY, EMPTY, EMPTY, EXIT_DEX},
  62. {EMPTY, EMPTY, EMPTY, NEXT_DEX, EXIT_DEX},
  63. {RADIO_1_DEX, RADIO_0_DEX, BACK_DEX, NEXT_DEX, EXIT_DEX},
  64. {EMPTY, EMPTY, BACK_DEX, NEXT_DEX, EXIT_DEX},
  65. {EMPTY, EMPTY, BACK_DEX, NEXT_DEX, EXIT_DEX},
  66. {LINK_DEX, EMPTY, BACK_DEX, EMPTY, FINISH_DEX},
  67. {EMPTY, EMPTY, EMPTY, EMPTY, EXIT_DEX}};
  68. UINT rgcMenu[] = {1, 2, 5, 3, 3, 3, 1};
  69. //////////////////////////////////////////////////////////////////////////
  70. // #defines
  71. //////////////////////////////////////////////////////////////////////////
  72. #define FLAG_HEIGHT 40
  73. #define FLAG_WIDTH 45
  74. #define MENUICON_HEIGHT 24
  75. #define MENUICON_WIDTH 24
  76. //////////////////////////////////////////////////////////////////////////
  77. // Code
  78. //////////////////////////////////////////////////////////////////////////
  79. typedef DWORD (WINAPI *PFNGETLAYOUT)(HDC); // gdi32!GetLayout
  80. typedef DWORD (WINAPI *PFNSETLAYOUT)(HDC, DWORD); // gdi32!SetLayout
  81. /**
  82. * This method is our contstructor for our class. It initialize all
  83. * of the instance data.
  84. */
  85. CDlgApp::CDlgApp()
  86. {
  87. g_fnBtnProc = NULL;
  88. m_hInstance = NULL;
  89. m_hwnd = NULL;
  90. m_fHighContrast = FALSE;
  91. m_fDynamicUpdate = TRUE;
  92. m_hfontTitle = NULL;
  93. m_hfontHeader = NULL;
  94. m_hfontMenu = NULL;
  95. m_hfontText = NULL;
  96. m_hbrPanel = NULL;
  97. m_hbrCenter = NULL;
  98. // store desktop width
  99. RECT rcDesktop;
  100. SystemParametersInfo(SPI_GETWORKAREA,0, &rcDesktop, FALSE);
  101. m_cDesktopWidth = rcDesktop.right - rcDesktop.left;
  102. m_cDesktopHeight = rcDesktop.bottom - rcDesktop.top;
  103. if (m_cDesktopWidth > 800)
  104. {
  105. m_f8by6 = TRUE;
  106. }
  107. else
  108. {
  109. m_f8by6 = FALSE;
  110. }
  111. m_hdcFlag = NULL;
  112. m_hdcFlagRTL = NULL;
  113. m_hdcGradientTop = NULL;
  114. m_hdcGradientTop256 = NULL;
  115. m_hdcGradientBottom = NULL;
  116. m_hdcGradientBottom256 = NULL;
  117. for (int i = 0; i < ARRAYSIZE(m_rghdcArrows); i++)
  118. {
  119. for (int j = 0; j < ARRAYSIZE(m_rghdcArrows[0]); j++)
  120. {
  121. for (int k = 0; k < ARRAYSIZE(m_rghdcArrows[0][0]); k++)
  122. {
  123. m_rghdcArrows[i][j][k] = NULL;
  124. }
  125. }
  126. }
  127. m_hcurHand = NULL;
  128. if (!IsCheckableOS())
  129. {
  130. m_dwScreen = 0; // machine cannot be checked
  131. m_iSelectedItem = EXIT_DEX;
  132. }
  133. else if (IsUserRestricted())
  134. {
  135. m_dwScreen = 6; // user does not have needed permissions to check machine
  136. m_iSelectedItem = EXIT_DEX;
  137. }
  138. else
  139. {
  140. m_dwScreen = 1; // first real page
  141. m_iSelectedItem = NEXT_DEX;
  142. }
  143. m_fLowColor = FALSE;
  144. m_iColors = -1;
  145. m_hpal = NULL;
  146. }
  147. CDlgApp::~CDlgApp()
  148. {
  149. DeleteObject(m_hfontTitle);
  150. DeleteObject(m_hfontHeader);
  151. DeleteObject(m_hfontMenu);
  152. DeleteObject(m_hfontText);
  153. DeleteObject(m_hbrPanel);
  154. DeleteObject(m_hbrCenter);
  155. DeleteDC(m_hdcFlag);
  156. DeleteDC(m_hdcFlagRTL);
  157. DeleteDC(m_hdcGradientTop);
  158. DeleteDC(m_hdcGradientTop256);
  159. DeleteDC(m_hdcGradientBottom);
  160. DeleteDC(m_hdcGradientBottom256);
  161. for (int i = 0; i < ARRAYSIZE(m_rghdcArrows); i++)
  162. {
  163. for (int j = 0; j < ARRAYSIZE(m_rghdcArrows[0]); j++)
  164. {
  165. for (int k = 0; k < ARRAYSIZE(m_rghdcArrows[0][0]); k++)
  166. {
  167. DeleteDC(m_rghdcArrows[i][j][k]);
  168. }
  169. }
  170. }
  171. }
  172. /**
  173. * This method will register our window class for the application.
  174. *
  175. * @param hInstance The application instance handle.
  176. *
  177. * @return No return value.
  178. */
  179. void CDlgApp::Register(HINSTANCE hInstance)
  180. {
  181. WNDCLASS wndclass;
  182. m_hInstance = hInstance;
  183. wndclass.style = CS_OWNDC | CS_DBLCLKS;
  184. wndclass.lpfnWndProc = s_WndProc;
  185. wndclass.cbClsExtra = 0;
  186. wndclass.cbWndExtra = 0;
  187. wndclass.hInstance = hInstance;
  188. wndclass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WEBAPP));
  189. wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
  190. wndclass.hbrBackground = NULL;
  191. wndclass.lpszMenuName = NULL;
  192. wndclass.lpszClassName = WINDOW_CLASS;
  193. RegisterClass(&wndclass);
  194. }
  195. /**
  196. * This method will initialize the data object.
  197. *
  198. * @return No return value.
  199. */
  200. BOOL CDlgApp::InitializeData(LPSTR pszCommandLine)
  201. {
  202. // Determine if we should use Direct Animaiton to display our intro graphics.
  203. // We don't use DA on slow machines, machines with less than 256 color displays,
  204. // and hydra terminals. For everything else we use DA.
  205. HWND hwnd = GetDesktopWindow();
  206. HDC hdc = GetDC( hwnd );
  207. m_iColors = GetDeviceCaps( hdc, NUMCOLORS );
  208. m_fLowColor = ((m_iColors != -1) && (m_iColors <= 256));
  209. if ( m_fLowColor )
  210. {
  211. m_hpal = CreateHalftonePalette(hdc);
  212. }
  213. // Are we in accesibility mode? This call won't work on NT 4.0 because this flag wasn't known.
  214. HIGHCONTRAST hc;
  215. hc.cbSize = sizeof(HIGHCONTRAST);
  216. hc.dwFlags = 0; // avoid random result should SPI fail
  217. if ( SystemParametersInfo( SPI_GETHIGHCONTRAST, sizeof(HIGHCONTRAST), &hc, 0 ) )
  218. {
  219. m_fHighContrast = ( hc.dwFlags & HCF_HIGHCONTRASTON );
  220. }
  221. else
  222. {
  223. // we must be on NT 4.0 or below. Just assume we aren't in high contrast mode.
  224. ASSERT( FALSE == m_fHighContrast );
  225. }
  226. // 210679: go to HighContrast mode if we're in 16-color mode as well
  227. if ( m_fLowColor && (m_iColors <= 16))
  228. {
  229. m_fHighContrast = TRUE;
  230. }
  231. // Set the color table based on our HighContrast mode setting.
  232. _SetColorTable();
  233. // create the fonts that we need to use.
  234. _CreateFonts(hdc);
  235. // create the images
  236. _CreateBitmaps();
  237. _CreateArrowBitmaps();
  238. _CreateGradientBitmaps();
  239. m_hcurHand = LoadCursor( m_hInstance, MAKEINTRESOURCE(IDC_BRHAND) );
  240. ReleaseDC(hwnd, hdc);
  241. return TRUE;
  242. }
  243. #define CENTER_RGB_VALUES RGB(90,126,220)
  244. #define PANEL_RGB_VALUES RGB(0,51,152)
  245. #define TITLE_RGB_VALUES RGB(255, 255, 255)
  246. #define HEADER_RGB_VALUES RGB(214, 223, 245)
  247. #define SHADOW_RGB_VALUES RGB(52, 98, 189)
  248. #define TEXT_RGB_VALUES RGB(255, 255, 255)
  249. #define DISABLED_RGB_VALUES RGB(128, 128, 128)
  250. BOOL CDlgApp::_SetColorTable()
  251. {
  252. if ( m_fHighContrast )
  253. {
  254. // set to high contrast values
  255. m_hbrPanel = (HBRUSH)(COLOR_BTNFACE+1);
  256. m_hbrCenter = (HBRUSH)(COLOR_WINDOW+1);
  257. m_crNormalText = GetSysColor(COLOR_WINDOWTEXT);
  258. m_crTitleText = m_crNormalText;
  259. m_crHeaderText = m_crNormalText;
  260. m_crCenterPanel = GetSysColor(COLOR_WINDOW);
  261. m_crBottomPanel = GetSysColor(COLOR_WINDOW);
  262. }
  263. else
  264. {
  265. m_crTitleText = TITLE_RGB_VALUES;
  266. m_crHeaderText = HEADER_RGB_VALUES;
  267. m_crShadow = SHADOW_RGB_VALUES;
  268. m_crNormalText = TEXT_RGB_VALUES;
  269. m_crCenterPanel = CENTER_RGB_VALUES;
  270. m_crBottomPanel = PANEL_RGB_VALUES;
  271. if ( !m_fLowColor )
  272. {
  273. m_hbrPanel = CreateSolidBrush( PANEL_RGB_VALUES );
  274. m_hbrCenter = CreateSolidBrush( CENTER_RGB_VALUES );
  275. }
  276. else
  277. {
  278. HBITMAP hbmp;
  279. hbmp = (HBITMAP)LoadImage(m_hInstance, MAKEINTRESOURCE(IDB_PANEL), IMAGE_BITMAP, 0,0, LR_CREATEDIBSECTION);
  280. if (hbmp)
  281. {
  282. m_hbrPanel = CreatePatternBrush(hbmp);
  283. DeleteObject(hbmp);
  284. }
  285. else
  286. {
  287. m_hbrPanel = (HBRUSH)(COLOR_BTNFACE+1);
  288. }
  289. hbmp = (HBITMAP)LoadImage(m_hInstance, MAKEINTRESOURCE(IDB_CENTER), IMAGE_BITMAP, 0,0, LR_CREATEDIBSECTION);
  290. if (hbmp)
  291. {
  292. m_hbrCenter = CreatePatternBrush(hbmp);
  293. DeleteObject(hbmp);
  294. }
  295. else
  296. {
  297. m_hbrCenter = (HBRUSH)(COLOR_WINDOW+1);
  298. }
  299. }
  300. }
  301. return TRUE;
  302. }
  303. // this is called once for each font that matches the fonts we care about
  304. int CALLBACK FoundFont
  305. (
  306. ENUMLOGFONTEX *lpelfe, // logical-font data
  307. NEWTEXTMETRICEX *lpntme, // physical-font data
  308. DWORD FontType, // type of font
  309. LPARAM lParam // application-defined data
  310. )
  311. {
  312. *((BOOL*)lParam) = TRUE;
  313. return 0;
  314. }
  315. BOOL CDlgApp::_CreateFonts(HDC hdc)
  316. {
  317. #define RGFONTDEX_LARGE 0
  318. #define RGFONTDEX_SMALL 1
  319. #define RGFONTDEX_TITLE 0
  320. #define RGFONTDEX_HEADER 1
  321. #define RGFONTDEX_MENU 2
  322. #define RGFONTDEX_FULL 0
  323. #define RGFONTDEX_BACKUP 1
  324. // [in] array of IDs, arranged by {title, header, menu} x { nice font, backup font}
  325. const int rgFontID[4][2] =
  326. {{IDS_FONTFACE_TITLE, IDS_FONTFACE_TITLE_BACKUP},
  327. {IDS_FONTFACE_HEADER,IDS_FONTFACE_HEADER_BACKUP},
  328. {IDS_FONTFACE_MENU, IDS_FONTFACE_MENU_BACKUP},
  329. {IDS_FONTFACE_TEXT, IDS_FONTFACE_TEXT_BACKUP}};
  330. // [in] array of heights, arranged by {large x small} x {title, header, menu} x { nice font, backup font}
  331. const int rgFontHeight[2][4][2] =
  332. {{{IDS_FONTCY_TITLE, IDS_FONTCY_TITLE_BACKUP},
  333. {IDS_FONTCY_HEADER, IDS_FONTCY_HEADER_BACKUP},
  334. {IDS_FONTCY_MENU, IDS_FONTCY_MENU_BACKUP},
  335. {IDS_FONTCY_TEXT, IDS_FONTCY_TEXT_BACKUP}},
  336. {{IDS_FONTCY_TITLE_LIL, IDS_FONTCY_TITLE_BACKUP_LIL},
  337. {IDS_FONTCY_HEADER_LIL, IDS_FONTCY_HEADER_BACKUP_LIL},
  338. {IDS_FONTCY_MENU_LIL, IDS_FONTCY_MENU_BACKUP_LIL},
  339. {IDS_FONTCY_TEXT_LIL, IDS_FONTCY_TEXT_BACKUP_LIL}}};
  340. // [out] array of pointers to the fonts
  341. HFONT* rgpFont[4] = {&m_hfontTitle, &m_hfontHeader, &m_hfontMenu, &m_hfontText};
  342. // [out] array of pointers heights of each font
  343. int* rgpcyFont[4] = {&m_cTitleFontHeight, &m_cHeaderFontHeight, &m_cMenuFontHeight, &m_cTextFontHeight};
  344. LOGFONT lf;
  345. CHARSETINFO csInfo;
  346. TCHAR szFontSize[6];
  347. for (int i = 0; i < ARRAYSIZE(rgpFont); i++)
  348. {
  349. memset(&lf,0,sizeof(lf));
  350. lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
  351. lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  352. lf.lfQuality = DEFAULT_QUALITY;
  353. lf.lfPitchAndFamily = DEFAULT_PITCH|FF_SWISS;
  354. LoadStringAuto( m_hInstance, rgFontID[i][RGFONTDEX_FULL], lf.lfFaceName, ARRAYSIZE(lf.lfFaceName) );
  355. // Set charset
  356. if (TranslateCharsetInfo((DWORD*)IntToPtr(GetACP()), &csInfo, TCI_SRCCODEPAGE) == 0)
  357. {
  358. csInfo.ciCharset = 0;
  359. }
  360. lf.lfCharSet = (BYTE)csInfo.ciCharset;
  361. // TODO: If user has accesibility large fonts turned on then scale the font sizes.
  362. LoadStringAuto( m_hInstance, rgFontHeight[m_f8by6 ? 0 : 1][i][RGFONTDEX_FULL], szFontSize, ARRAYSIZE(szFontSize) );
  363. *(rgpcyFont[i]) = MulDiv((_ttoi(szFontSize)), GetDeviceCaps(hdc, LOGPIXELSY), 72);
  364. lf.lfHeight = -(*(rgpcyFont[i]));
  365. BOOL fFound = FALSE;
  366. EnumFontFamiliesEx(hdc, &lf, (FONTENUMPROC)FoundFont, (LPARAM)&fFound, 0);
  367. if (!fFound)
  368. {
  369. LoadStringAuto( m_hInstance, rgFontID[i][RGFONTDEX_BACKUP], lf.lfFaceName, ARRAYSIZE(lf.lfFaceName) );
  370. LoadStringAuto( m_hInstance, rgFontHeight[m_f8by6 ? 0 : 1][i][RGFONTDEX_BACKUP], szFontSize, ARRAYSIZE(szFontSize) );
  371. *(rgpcyFont[i]) = MulDiv((_ttoi(szFontSize)), GetDeviceCaps(hdc, LOGPIXELSY), 72);
  372. lf.lfHeight = -(*(rgpcyFont[i]));
  373. }
  374. *(rgpFont[i]) = CreateFontIndirect(&lf);
  375. }
  376. return TRUE;
  377. }
  378. #define BITMAPTYPE_NORMAL 0x0
  379. #define BITMAPTYPE_LOWCOLOR 0x1
  380. BOOL CDlgApp::_CreateBitmaps()
  381. {
  382. const int rgiBitmapID[2][2] = {{IDB_FLAG, IDB_FLAG_256}, {IDB_FLAG_RTL, IDB_FLAG_RTL_256}}; // [in]
  383. HDC* rgphdc[2] = {&m_hdcFlag, &m_hdcFlagRTL}; // [out]
  384. int iBitmapType = (m_fLowColor) ? BITMAPTYPE_LOWCOLOR : BITMAPTYPE_NORMAL;
  385. for (int i = 0; i < ARRAYSIZE(rgphdc); i++)
  386. {
  387. HBITMAP hbm;
  388. BITMAP bm;
  389. *(rgphdc[i]) = CreateCompatibleDC(NULL);
  390. hbm = (HBITMAP)LoadImage(m_hInstance, MAKEINTRESOURCE(rgiBitmapID[i][iBitmapType]), IMAGE_BITMAP, 0,0, LR_CREATEDIBSECTION);
  391. GetObject(hbm,sizeof(bm),&bm);
  392. SelectObject( *(rgphdc[i]), hbm );
  393. }
  394. return TRUE;
  395. }
  396. BOOL CDlgApp::_CreateArrowBitmaps()
  397. {
  398. const int rgiBitmapID[2][6][2] =
  399. {{{IDB_BACK, IDB_BACK_HOVER},
  400. {IDB_NEXT, IDB_NEXT_HOVER},
  401. {IDB_CLOSE, IDB_CLOSE_HOVER},
  402. {IDB_CANCEL, IDB_CANCEL_HOVER},
  403. {IDB_RADIO_ON, IDB_RADIO_ON_HOVER},
  404. {IDB_RADIO_OFF, IDB_RADIO_OFF_HOVER}},
  405. {{IDB_BACK_256, IDB_BACK_HOVER_256},
  406. {IDB_NEXT_256, IDB_NEXT_HOVER_256},
  407. {IDB_CLOSE_256, IDB_CLOSE_HOVER_256},
  408. {IDB_CANCEL_256, IDB_CANCEL_HOVER_256},
  409. {IDB_RADIO_ON_256, IDB_RADIO_ON_HOVER_256},
  410. {IDB_RADIO_OFF_256, IDB_RADIO_OFF_HOVER_256}}}; // [in]
  411. for (int i = 0; i < ARRAYSIZE(m_rghdcArrows); i++)
  412. {
  413. for (int j = 0; j < ARRAYSIZE(m_rghdcArrows[0]); j++)
  414. {
  415. for (int k = 0; k < ARRAYSIZE(m_rghdcArrows[0][0]); k++)
  416. {
  417. HBITMAP hbm;
  418. BITMAP bm;
  419. m_rghdcArrows[i][j][k] = CreateCompatibleDC(NULL);
  420. hbm = (HBITMAP)LoadImage(m_hInstance, MAKEINTRESOURCE(rgiBitmapID[i][j][k]), IMAGE_BITMAP, 0,0, LR_CREATEDIBSECTION);
  421. GetObject(hbm,sizeof(bm),&bm);
  422. SelectObject( m_rghdcArrows[i][j][k], hbm );
  423. }
  424. }
  425. }
  426. return TRUE;
  427. }
  428. BOOL CDlgApp::_CreateGradientBitmaps()
  429. {
  430. const int rgiBitmapID[4] = {IDB_GRADIENT_TOP, IDB_GRADIENT_TOP_256, IDB_GRADIENT_BOTTOM, IDB_GRADIENT_BOTTOM_256}; // [in]
  431. HDC* rgphdc[4] = {&m_hdcGradientTop, &m_hdcGradientTop256, &m_hdcGradientBottom, &m_hdcGradientBottom256}; // [out]
  432. for (int i = 0; i < ARRAYSIZE(rgphdc); i++)
  433. {
  434. HBITMAP hbm;
  435. BITMAP bm;
  436. *(rgphdc[i]) = CreateCompatibleDC(NULL);
  437. hbm = (HBITMAP)LoadImage(m_hInstance, MAKEINTRESOURCE(rgiBitmapID[i]), IMAGE_BITMAP, 0,0, LR_CREATEDIBSECTION);
  438. GetObject(hbm,sizeof(bm),&bm);
  439. SelectObject( *(rgphdc[i]), hbm );
  440. }
  441. return TRUE;
  442. }
  443. UINT CDlgApp::_StringWidth(HDC hdc, UINT idString, INT iLogPixelSx)
  444. {
  445. TCHAR szBuffer[256];
  446. SIZE size;
  447. LoadString(m_hInstance, idString, szBuffer, ARRAYSIZE(szBuffer));
  448. GetTextExtentPoint32(hdc, szBuffer, lstrlen(szBuffer), &size);
  449. return (size.cx * iLogPixelSx) / 80;
  450. }
  451. UINT CDlgApp::_StringHeight(HDC hdc, UINT idString, INT iLogPixelSy)
  452. {
  453. TCHAR szBuffer[256];
  454. SIZE size;
  455. LoadString(m_hInstance, idString, szBuffer, ARRAYSIZE(szBuffer));
  456. GetTextExtentPoint32(hdc, szBuffer, lstrlen(szBuffer), &size);
  457. return (size.cy * iLogPixelSy) / 80;
  458. }
  459. BOOL CDlgApp::_AdjustIconPlacement()
  460. {
  461. HDC hdc = GetDC(m_hwnd);
  462. UINT cx;
  463. if (hdc)
  464. {
  465. UINT i;
  466. INT iLogPixelSx = GetDeviceCaps(hdc, LOGPIXELSX);
  467. cWidthIconText[0] = m_f8by6 ? 250 : 200;
  468. cWidthIconText[1] = m_f8by6 ? 250 : 200;
  469. cWidthIconText[2] = _StringWidth(hdc, IDS_MENULABEL1, iLogPixelSx); // BACK
  470. cWidthIconText[3] = _StringWidth(hdc, IDS_MENULABEL2, iLogPixelSx); // NEXT
  471. // iterate over CANCEL, FINISH
  472. cWidthIconText[4] = 0;
  473. for (i = IDS_MENULABEL0; i <= IDS_MENULABEL3; i += 3)
  474. {
  475. cx = _StringWidth(hdc, i, iLogPixelSx);
  476. if (cx > cWidthIconText[4])
  477. {
  478. cWidthIconText[4] = cx;
  479. }
  480. }
  481. ReleaseDC(m_hwnd, hdc);
  482. cx = cWidthIconText[4];
  483. rgPtIconText[4].x = rgPtIcons[4].x - cx - BUTTONTEXTGAP; // cancel/finish text
  484. rgPtIconText640[4].x = rgPtIcons640[4].x - cx - BUTTONTEXTGAP; // cancel/finish text
  485. rgPtIcons[3].x = rgPtIconText[4].x - MENUICON_WIDTH - TRANSBUTTONGAP; // next button
  486. rgPtIcons640[3].x = rgPtIconText640[4].x - MENUICON_WIDTH - TRANSBUTTONGAP; // next button
  487. cx = _StringWidth(hdc, IDS_MENULABEL2, iLogPixelSx);
  488. rgPtIconText[3].x = rgPtIcons[3].x - cx - BUTTONTEXTGAP; // next text
  489. rgPtIconText640[3].x = rgPtIcons640[3].x - cx - BUTTONTEXTGAP; // next text
  490. rgPtIcons[2].x = rgPtIconText[3].x - MENUICON_WIDTH - TRANSBUTTONGAP; // back button
  491. rgPtIcons640[2].x = rgPtIconText640[3].x - MENUICON_WIDTH - TRANSBUTTONGAP; // back button
  492. cx = _StringWidth(hdc, IDS_MENULABEL1, iLogPixelSx);
  493. rgPtIconText[2].x = rgPtIcons[2].x - cx - BUTTONTEXTGAP; // back text
  494. rgPtIconText640[2].x = rgPtIcons640[2].x - cx - BUTTONTEXTGAP; // back text
  495. }
  496. return TRUE;
  497. }
  498. BOOL CDlgApp::_AdjustToFitFonts()
  499. {
  500. HDC hdc = GetDC(m_hwnd);
  501. if (hdc)
  502. {
  503. SetMapMode(hdc,MM_TEXT);
  504. INT iLogPixelSy = GetDeviceCaps(hdc, LOGPIXELSY);
  505. for (UINT i = 0; i < ARRAYSIZE(rgPtIcons); i++ )
  506. {
  507. UINT dex = rgdwMenuByPos[m_dwScreen][i];
  508. if (EMPTY != dex)
  509. {
  510. POINT pt = *((m_f8by6) ? &rgPtIconText[i] : &rgPtIconText640[i]);
  511. HWND hwnd = GetDlgItem(m_hwnd, IDM_MENUITEM0+i);
  512. SetWindowPos(hwnd, NULL, pt.x, pt.y, cWidthIconText[i], (3 * _StringHeight(hdc, rgdwLabel[dex], iLogPixelSy)) / 2, SWP_NOZORDER );
  513. }
  514. }
  515. ReleaseDC(m_hwnd, hdc);
  516. }
  517. return TRUE;
  518. }
  519. #define BITMAPSTUFF(rgarrows) {phdcBitmap = (m_iSelectedItem == rgdwMenuByPos[m_dwScreen][i]) ? &(rgarrows[1]) : &(rgarrows[0]); }
  520. BOOL CDlgApp::_DrawMenuIcons(BOOL fEraseBackground)
  521. {
  522. RECT rect;
  523. UINT i;
  524. HDC hdc = GetDC(m_hwnd);
  525. if (hdc)
  526. {
  527. HPALETTE hpalOld = NULL;
  528. if ( m_hpal )
  529. {
  530. hpalOld = SelectPalette(hdc, m_hpal, FALSE);
  531. RealizePalette(hdc);
  532. }
  533. HDC* phdcBitmap;
  534. for (i=0; i < ARRAYSIZE(rgPtIcons); i++ )
  535. {
  536. switch (rgdwMenuByPos[m_dwScreen][i])
  537. {
  538. case EMPTY:
  539. continue;
  540. case BACK_DEX:
  541. BITMAPSTUFF(m_rghdcArrows[m_fLowColor ? 1 : 0][0]);
  542. break;
  543. case NEXT_DEX:
  544. case LINK_DEX:
  545. BITMAPSTUFF(m_rghdcArrows[m_fLowColor ? 1 : 0][1]);
  546. break;
  547. case FINISH_DEX:
  548. BITMAPSTUFF(m_rghdcArrows[m_fLowColor ? 1 : 0][2]);
  549. break;
  550. case EXIT_DEX:
  551. BITMAPSTUFF(m_rghdcArrows[m_fLowColor ? 1 : 0][3]);
  552. break;
  553. case RADIO_1_DEX:
  554. BITMAPSTUFF(m_rghdcArrows[m_fLowColor ? 1 : 0][m_fDynamicUpdate ? 4 : 5]);
  555. break;
  556. case RADIO_0_DEX:
  557. BITMAPSTUFF(m_rghdcArrows[m_fLowColor ? 1 : 0][m_fDynamicUpdate ? 5 : 4]);
  558. break;
  559. }
  560. rect.left = m_f8by6 ? rgPtIcons[i].x : rgPtIcons640[i].x;
  561. rect.top = m_f8by6 ? rgPtIcons[i].y : rgPtIcons640[i].y;
  562. rect.right = rect.left + MENUICON_WIDTH; // arrow width
  563. rect.bottom = rect.top + MENUICON_HEIGHT; // arrow height as well
  564. BitBlt( hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, *phdcBitmap, 0,0, SRCCOPY );
  565. }
  566. if(hpalOld)
  567. SelectPalette(hdc, hpalOld, FALSE);
  568. ReleaseDC(m_hwnd, hdc);
  569. }
  570. return TRUE;
  571. }
  572. void CDlgApp::_InvalidateRectIntl(HWND hwnd, RECT* pRect, BOOL fBackgroundClear)
  573. {
  574. RECT* pRectToUse = pRect; // default to normal case (don't flip)
  575. RECT rectRTL;
  576. if (pRect)
  577. {
  578. OSVERSIONINFO osvi;
  579. if (GetVersionEx(&osvi) &&
  580. (osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) &&
  581. Mirror_IsWindowMirroredRTL(hwnd)) // right to left on Win9X
  582. {
  583. rectRTL.top = pRect->top;
  584. rectRTL.bottom = pRect->bottom;
  585. rectRTL.right = m_cxClient - pRect->left;
  586. rectRTL.left = m_cxClient - pRect->right;
  587. pRectToUse = &rectRTL;
  588. }
  589. }
  590. InvalidateRect(hwnd, pRectToUse, fBackgroundClear);
  591. }
  592. /**
  593. * This method will create the application window.
  594. *
  595. * @return No return value.
  596. */
  597. void CDlgApp::Create(int nCmdShow)
  598. {
  599. //
  600. // load the window title from the resource.
  601. //
  602. TCHAR szTitle[MAX_PATH];
  603. LoadStringAuto(m_hInstance, IDS_TITLEBAR, szTitle, MAX_PATH);
  604. DWORD dwStyle = WS_OVERLAPPED | WS_MINIMIZEBOX | WS_CAPTION | WS_SYSMENU | WS_BORDER | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
  605. if (m_f8by6)
  606. {
  607. m_cxClient = 800;
  608. m_cyClient = 600;
  609. }
  610. else
  611. {
  612. m_cxClient = 640;
  613. m_cyClient = 460;
  614. }
  615. m_hwnd = CreateWindowEx(
  616. WS_EX_CONTROLPARENT,
  617. WINDOW_CLASS,
  618. szTitle,
  619. dwStyle,
  620. 0,
  621. 0,
  622. m_cxClient,
  623. m_cyClient,
  624. NULL,
  625. NULL,
  626. m_hInstance,
  627. this);
  628. // set the client area to a fixed size and center the window on screen
  629. RECT rect = {0};
  630. rect.left = (m_cDesktopWidth - m_cxClient) / 2;
  631. rect.top = (m_cDesktopHeight - m_cyClient) / 2;
  632. rect.right = m_cDesktopWidth - rect.left;
  633. rect.bottom = m_cDesktopHeight - rect.top;
  634. AdjustWindowRect( &rect, dwStyle, FALSE );
  635. SetWindowPos(m_hwnd, NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER);
  636. ShowWindow(m_hwnd, SW_SHOW);
  637. m_cxTopPanel = m_f8by6 ? 80 : 84;
  638. m_cyBottomPanel = m_f8by6 ? 501 : 391;
  639. _InvalidateRectIntl(m_hwnd, NULL, TRUE);
  640. }
  641. /**
  642. * This method is our application message loop.
  643. *
  644. * @return No return value.
  645. */
  646. void CDlgApp::MessageLoop()
  647. {
  648. MSG msg;
  649. while (GetMessage(&msg, NULL, 0, 0))
  650. {
  651. // IsDialogMessage cannot understand the concept of ownerdraw default pushbuttons. It treats
  652. // these attributes as mutually exclusive. As a result, we handle this ourselves. We want
  653. // whatever control has focus to act as the default pushbutton.
  654. if ( (WM_KEYDOWN == msg.message) && (VK_RETURN == msg.wParam) )
  655. {
  656. HWND hwndFocus = GetFocus();
  657. if ( hwndFocus )
  658. {
  659. SendMessage(m_hwnd, WM_COMMAND, MAKELONG(GetDlgCtrlID(hwndFocus), BN_CLICKED), (LPARAM)hwndFocus);
  660. }
  661. continue;
  662. }
  663. if ( IsDialogMessage(m_hwnd, &msg) )
  664. continue;
  665. TranslateMessage(&msg);
  666. DispatchMessage(&msg);
  667. }
  668. }
  669. /**
  670. * This is the window procedure for the container application. It is used
  671. * to deal with all messages to our window.
  672. *
  673. * @param hwnd Window handle.
  674. * @param msg The window message.
  675. * @param wParam Window Parameter.
  676. * @param lParam Window Parameter.
  677. *
  678. * @return LRESULT
  679. */
  680. LRESULT CALLBACK CDlgApp::s_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  681. {
  682. CDlgApp *pThis = (CDlgApp *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  683. switch(msg)
  684. {
  685. case WM_NCCREATE:
  686. {
  687. CDlgApp* pThisCreate = (CDlgApp *)(((LPCREATESTRUCT)lParam)->lpCreateParams);
  688. SetWindowLongPtr(hwnd, GWLP_USERDATA, (LRESULT)pThisCreate);
  689. }
  690. break;
  691. case WM_CREATE:
  692. return pThis->OnCreate(hwnd);
  693. case WM_DESTROY:
  694. return pThis->OnDestroy();
  695. case WM_ACTIVATE:
  696. return pThis->OnActivate(wParam);
  697. case WM_PAINT:
  698. return pThis->OnPaint((HDC)wParam);
  699. case WM_ERASEBKGND:
  700. return pThis->OnEraseBkgnd((HDC)wParam);
  701. case WM_LBUTTONUP:
  702. return pThis->OnLButtonUp(LOWORD(lParam), HIWORD(lParam), (DWORD)wParam);
  703. case WM_MOUSEMOVE:
  704. return pThis->OnMouseMove(LOWORD(lParam), HIWORD(lParam), (DWORD)wParam);
  705. case WM_SETCURSOR:
  706. return pThis->OnSetCursor((HWND)wParam, LOWORD(lParam), HIWORD(lParam));
  707. case WM_SETFOCUS:
  708. SetFocus(GetDlgItem(hwnd, IDM_MENUITEM0 + rgdwPosition[pThis->m_iSelectedItem]));
  709. return TRUE;
  710. case WM_TIMER:
  711. if (LAUNCHTIMER == wParam)
  712. {
  713. KillTimer(hwnd, LAUNCHTIMER);
  714. pThis->OnLaunchApp();
  715. return TRUE;
  716. }
  717. break;
  718. case WM_COMMAND:
  719. case WM_SYSCOMMAND:
  720. if ( pThis->OnCommand(LOWORD(wParam)) )
  721. return 0;
  722. break;
  723. case WM_DRAWITEM:
  724. return pThis->OnDrawItem((UINT)wParam, (LPDRAWITEMSTRUCT)lParam);
  725. case WM_QUERYNEWPALETTE:
  726. return pThis->OnQueryNewPalette();
  727. case WM_PALETTECHANGED:
  728. return pThis->OnPaletteChanged((HWND)wParam);
  729. case ARM_CHANGESCREEN:
  730. return pThis->OnChangeScreen((DWORD)wParam);
  731. }
  732. return DefWindowProc(hwnd, msg, wParam, lParam);
  733. }
  734. /**
  735. * This method is called on WM_CREATE.
  736. *
  737. * @param hwnd Window handle for the application.
  738. *
  739. * @return No return value.
  740. */
  741. LRESULT CDlgApp::OnCreate(HWND hwnd)
  742. {
  743. m_hwnd = hwnd;
  744. _CreateMenu();
  745. _RedrawMenu();
  746. SetFocus(GetDlgItem(m_hwnd, IDM_MENUITEM0 + rgdwPosition[m_iSelectedItem]));
  747. return 0;
  748. }
  749. void CDlgApp::_CreateMenu()
  750. {
  751. // Create one window for each button. These windows will get resized and moved
  752. // after we call AdjustToFitFonts.
  753. for (UINT i = 0; i < ARRAYSIZE(rgPtIcons); i++)
  754. {
  755. HWND hwnd = CreateWindowEx(
  756. 0,
  757. TEXT("BUTTON"),
  758. TEXT(""),
  759. WS_CHILD|WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_VISIBLE|WS_TABSTOP|BS_PUSHBUTTON|BS_MULTILINE|BS_OWNERDRAW,
  760. 0,0,0,0,
  761. m_hwnd,
  762. NULL,
  763. m_hInstance,
  764. NULL );
  765. SetWindowLongPtr(hwnd, GWLP_ID, IDM_MENUITEM0 + i);
  766. SendMessage(hwnd, WM_SETFONT, (WPARAM)m_hfontMenu, 0);
  767. g_fnBtnProc = (WNDPROC)SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)s_ButtonWndProc);
  768. }
  769. // We created the windows with zero size, now we adjust that size to take into
  770. // account for the selected font size, etc.
  771. _AdjustIconPlacement();
  772. _AdjustToFitFonts();
  773. }
  774. void CDlgApp::_RedrawMenu()
  775. {
  776. for (UINT i = 0; i < ARRAYSIZE(rgPtIcons); i++)
  777. {
  778. if (EMPTY != rgdwMenuByPos[m_dwScreen][i])
  779. {
  780. TCHAR szBuffer[100];
  781. LoadString(m_hInstance, rgdwLabel[rgdwMenuByPos[m_dwScreen][i]], szBuffer, ARRAYSIZE(szBuffer));
  782. SetWindowText(GetDlgItem(m_hwnd, IDM_MENUITEM0+i), szBuffer);
  783. EnableWindow(GetDlgItem(m_hwnd, IDM_MENUITEM0+i), TRUE);
  784. ShowWindow(GetDlgItem(m_hwnd, IDM_MENUITEM0+i), TRUE);
  785. }
  786. else
  787. {
  788. EnableWindow(GetDlgItem(m_hwnd, IDM_MENUITEM0+i), FALSE);
  789. ShowWindow(GetDlgItem(m_hwnd, IDM_MENUITEM0+i), FALSE);
  790. }
  791. // setting window text only actually sets the accelerator, real drawing of text is in OnDrawItem
  792. }
  793. _AdjustToFitFonts();
  794. }
  795. /**
  796. * This method handles the WM_DESTROY message.
  797. *
  798. * @return No return value.
  799. */
  800. LRESULT CDlgApp::OnDestroy()
  801. {
  802. // ensure this is the last message we care about
  803. SetWindowLongPtr(m_hwnd, GWLP_USERDATA, 0);
  804. PostQuitMessage(0);
  805. return 0;
  806. }
  807. LRESULT CDlgApp::OnActivate(WPARAM wParam)
  808. {
  809. return 0;
  810. }
  811. /**
  812. * This method handles the WM_PAINT message.
  813. *
  814. * @return No return value.
  815. */
  816. LRESULT CDlgApp::OnPaint(HDC hdc)
  817. {
  818. PAINTSTRUCT ps;
  819. BeginPaint(m_hwnd,&ps);
  820. RECT rect;
  821. HPALETTE hpalOld = NULL;
  822. if ( m_hpal )
  823. {
  824. hpalOld = SelectPalette(hdc, m_hpal, FALSE);
  825. RealizePalette(hdc);
  826. }
  827. SetMapMode(hdc, MM_TEXT);
  828. _PaintFlagBitmap();
  829. _DrawMenuIcons(FALSE);
  830. // restore the DC to its original value
  831. if(hpalOld)
  832. SelectPalette(hdc, hpalOld, FALSE);
  833. EndPaint(m_hwnd,&ps);
  834. return 0;
  835. }
  836. /**
  837. * This method handles the WM_ERASEBKGND message.
  838. *
  839. * @return No return value.
  840. */
  841. LRESULT CDlgApp::OnEraseBkgnd(HDC hdc)
  842. {
  843. RECT rect;
  844. HPALETTE hpalOld = NULL;
  845. if ( m_hpal )
  846. {
  847. hpalOld = SelectPalette(hdc, m_hpal, FALSE);
  848. RealizePalette(hdc);
  849. }
  850. SetMapMode(hdc, MM_TEXT);
  851. SetBkMode(hdc, TRANSPARENT);
  852. // Draw the top pane:
  853. rect.left = 0;
  854. rect.top = 0;
  855. rect.right = m_cxClient;
  856. rect.bottom = m_cxTopPanel;
  857. if (m_f8by6 && !m_fLowColor)
  858. {
  859. BitBlt( hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, m_hdcGradientTop, 0,0, SRCCOPY );
  860. }
  861. else if (m_f8by6 && m_fLowColor && (m_iColors > 16))
  862. {
  863. BitBlt( hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, m_hdcGradientTop256, 0,0, SRCCOPY );
  864. }
  865. else
  866. {
  867. FillRect(hdc, &rect, m_hbrPanel);
  868. }
  869. // Draw center pane
  870. rect.left = 0;
  871. rect.top = m_cxTopPanel;
  872. rect.right = m_cxClient;
  873. rect.bottom = m_cyBottomPanel;
  874. FillRect(hdc, &rect, m_hbrCenter);
  875. // Draw the bottom pane:
  876. rect.left = 0;
  877. rect.top = m_cyBottomPanel;
  878. rect.right = m_cxClient;
  879. rect.bottom = m_cyClient;
  880. if (m_f8by6 && !m_fLowColor)
  881. {
  882. BitBlt( hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top + 1, m_hdcGradientBottom, 0,0, SRCCOPY );
  883. }
  884. else if (m_f8by6 && m_fLowColor && (m_iColors > 16))
  885. {
  886. BitBlt( hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top + 1, m_hdcGradientBottom256, 0,0, SRCCOPY );
  887. }
  888. else
  889. {
  890. FillRect(hdc, &rect, m_hbrPanel);
  891. }
  892. // Draw the text
  893. _DrawText(hdc);
  894. if(hpalOld)
  895. {
  896. SelectPalette(hdc, hpalOld, FALSE);
  897. }
  898. return TRUE;
  899. }
  900. void CDlgApp::_DrawText(HDC hdc)
  901. {
  902. HFONT* rgFontText[4] = {&m_hfontTitle, &m_hfontHeader, &m_hfontText, &m_hfontText};
  903. BOOL rgfShadowText[4] = {FALSE, TRUE, FALSE, FALSE};
  904. SetTextColor(hdc,m_crNormalText);
  905. HFONT hfontOld = (HFONT)SelectObject(hdc,m_hfontHeader); // first draw uses hfontHeader
  906. for (int i = TEXT_TITLE; i <= TEXT_SUB; i++)
  907. {
  908. TCHAR szBuffer[2048];
  909. SelectObject(hdc, *rgFontText[i]);
  910. LoadString(m_hInstance, rgdwText[m_dwScreen][i], szBuffer, ARRAYSIZE(szBuffer));
  911. if (rgfShadowText[i] && !m_fHighContrast)
  912. {
  913. SetTextColor(hdc,m_crShadow);
  914. RECT rectShadow;
  915. memcpy(&rectShadow, (m_f8by6) ? &(rgrectText[i]) : &(rgrectText640[i]), sizeof(rectShadow));
  916. rectShadow.left += 2; rectShadow.right += 2; rectShadow.top += 2; rectShadow.bottom += 2;
  917. DrawText(hdc,szBuffer,-1, &rectShadow, DT_NOCLIP|DT_WORDBREAK);
  918. SetTextColor(hdc,m_crTitleText);
  919. }
  920. DrawText(hdc,szBuffer,-1, (m_f8by6) ? &(rgrectText[i]) : &(rgrectText640[i]), DT_NOCLIP|DT_WORDBREAK);
  921. }
  922. // restore the DC to its original value
  923. SelectObject(hdc,hfontOld);
  924. }
  925. void CDlgApp::_PaintFlagBitmap()
  926. {
  927. HDC hdc = GetDC(m_hwnd);
  928. if (hdc)
  929. {
  930. RECT rect;
  931. if (m_f8by6)
  932. {
  933. rect.left = 20;
  934. rect.top = 10;
  935. }
  936. else
  937. {
  938. rect.left = 20;
  939. rect.top = 20;
  940. }
  941. rect.right = rect.left + FLAG_WIDTH;
  942. rect.bottom = rect.top + FLAG_HEIGHT;
  943. BitBlt( hdc, rect.left, rect.top, FLAG_WIDTH, FLAG_HEIGHT,
  944. Mirror_IsWindowMirroredRTL(m_hwnd) ? m_hdcFlagRTL : m_hdcFlag,
  945. 0,0, SRCCOPY); // don't mirror flag on RTL systems for trademark reasons
  946. ReleaseDC(m_hwnd, hdc);
  947. }
  948. }
  949. BOOL CDlgApp::_GetButtonIntersect(int x, int y, UINT* pidMenuItem)
  950. {
  951. POINT pt;
  952. pt.x = x;
  953. pt.y = y;
  954. for (UINT i = 0; i < rgcMenu[m_dwScreen]; i++)
  955. {
  956. UINT iPos = rgdwPosition[rgdwMenu[m_dwScreen][i]];
  957. RECT rect;
  958. rect.left = m_f8by6 ? rgPtIcons[iPos].x : rgPtIcons640[iPos].x;
  959. rect.top = m_f8by6 ? rgPtIcons[iPos].y : rgPtIcons640[iPos].y;
  960. rect.right = rect.left + MENUICON_WIDTH;
  961. rect.bottom = rect.top + MENUICON_HEIGHT;
  962. // extend the "hot zone" of the button to the right of the button by this amount to close the gap
  963. // between the button and the menu item
  964. switch (rgdwMenu[m_dwScreen][i])
  965. {
  966. case EXIT_DEX:
  967. case BACK_DEX:
  968. case NEXT_DEX:
  969. case FINISH_DEX:
  970. rect.left -= 6; // for items with text to the left of the button, we extend to the left
  971. break;
  972. case LINK_DEX:
  973. case RADIO_1_DEX:
  974. case RADIO_0_DEX:
  975. rect.right += 6; // for items with text to the right of the button, we extend to the right
  976. }
  977. if (PtInRect(&rect, pt))
  978. {
  979. *pidMenuItem = IDM_MENUITEM0 + iPos;
  980. return TRUE;
  981. }
  982. }
  983. return FALSE;
  984. }
  985. LRESULT CDlgApp::OnMouseMove(int x, int y, DWORD fwKeys)
  986. {
  987. if (GetForegroundWindow() == m_hwnd) // only care if we have focus
  988. {
  989. UINT idMenuItem;
  990. if (_GetButtonIntersect(x, y, &idMenuItem))
  991. {
  992. SetFocus(GetDlgItem(m_hwnd, idMenuItem));
  993. SetCursor(m_hcurHand);
  994. }
  995. else
  996. {
  997. SetCursor(LoadCursor(NULL,IDC_ARROW));
  998. }
  999. }
  1000. return 0;
  1001. }
  1002. LRESULT CDlgApp::OnLButtonUp(int x, int y, DWORD fwKeys)
  1003. {
  1004. if (GetForegroundWindow() == m_hwnd) // only care if we have focus
  1005. {
  1006. UINT idMenuItem;
  1007. if (_GetButtonIntersect(x, y, &idMenuItem))
  1008. {
  1009. OnCommand(idMenuItem);
  1010. }
  1011. }
  1012. return 0;
  1013. }
  1014. LRESULT CDlgApp::OnSetCursor(HWND hwnd, int nHittest, int wMouseMsg)
  1015. {
  1016. if (GetForegroundWindow() == m_hwnd) // only care if we have focus
  1017. {
  1018. if ( hwnd != m_hwnd )
  1019. {
  1020. SetCursor(m_hcurHand);
  1021. return TRUE;
  1022. }
  1023. SetCursor(LoadCursor(NULL,IDC_ARROW));
  1024. }
  1025. return TRUE;
  1026. }
  1027. LRESULT CDlgApp::OnChangeScreen(DWORD dwScreen)
  1028. {
  1029. static DWORD dwSelectedOld; // we store the last position on the main screen
  1030. m_dwScreen += dwScreen;
  1031. _RedrawMenu();
  1032. HDC hdc = GetDC(m_hwnd);
  1033. if (hdc)
  1034. {
  1035. _DrawText(hdc);
  1036. ReleaseDC(m_hwnd, hdc);
  1037. }
  1038. // invalidate the text
  1039. _InvalidateRectIntl(m_hwnd, NULL, TRUE);
  1040. m_iSelectedItem = rgdwMenuByPos[m_dwScreen][rgdwPosition[m_iSelectedItem]];
  1041. if (EMPTY == m_iSelectedItem)
  1042. {
  1043. m_iSelectedItem = rgdwMenu[m_dwScreen][rgcMenu[m_dwScreen] - 1];
  1044. SetFocus(GetDlgItem(m_hwnd, IDM_MENUITEM0 + rgdwPosition[m_iSelectedItem]));
  1045. }
  1046. return TRUE;
  1047. }
  1048. LRESULT CDlgApp::OnLaunchApp()
  1049. {
  1050. BOOL fResult = FALSE;
  1051. TCHAR szDirectory[MAX_PATH];
  1052. // first, pop up the "please wait" dialog
  1053. HWND hwndWait = CreateDialog(m_hInstance, MAKEINTRESOURCE(IDD_WAIT), GetDesktopWindow(), (DLGPROC)s_WaitWndProc);
  1054. if (hwndWait)
  1055. {
  1056. RECT popupSize = {0, 0, 175, 50}; // a good guess
  1057. GetWindowRect(hwndWait, &popupSize);
  1058. SetWindowPos(hwndWait, HWND_TOP,
  1059. (m_cDesktopWidth - (popupSize.right - popupSize.left)) / 2 ,
  1060. (m_cDesktopHeight - (popupSize.bottom - popupSize.top)) / 2,
  1061. 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE);
  1062. }
  1063. // then launch the app itself
  1064. if (GetModuleFileName(NULL, szDirectory, ARRAYSIZE(szDirectory)) &&
  1065. _PathRemoveFileSpec(szDirectory))
  1066. {
  1067. TCHAR szBuffer[256];
  1068. TCHAR szArgsBuffer[256];
  1069. LoadStringAuto(m_hInstance, IDS_EXECUTABLE, szBuffer, ARRAYSIZE(szBuffer));
  1070. LoadStringAuto(m_hInstance,
  1071. m_fDynamicUpdate ? IDS_EXECUTABLE_ARGS_DU : IDS_EXECUTABLE_ARGS_NODU,
  1072. szArgsBuffer, ARRAYSIZE(szArgsBuffer));
  1073. fResult = ((INT_PTR)ShellExecute(m_hwnd, NULL, szBuffer, szArgsBuffer, szDirectory, SW_SHOWNORMAL ) > 32);
  1074. }
  1075. return fResult;
  1076. }
  1077. LRESULT CDlgApp::OnNextButton()
  1078. {
  1079. switch (m_dwScreen)
  1080. {
  1081. case 4: // on change to last screen, we launch the app
  1082. SetTimer(m_hwnd, LAUNCHTIMER, 100, NULL);
  1083. break;
  1084. }
  1085. return TRUE;
  1086. }
  1087. LRESULT CDlgApp::OnCommand(int wID)
  1088. {
  1089. BOOL fRetVal = FALSE;
  1090. switch(wID)
  1091. {
  1092. case IDM_MENUITEM0:
  1093. case IDM_MENUITEM1:
  1094. case IDM_MENUITEM2:
  1095. case IDM_MENUITEM3:
  1096. case IDM_MENUITEM4:
  1097. switch (rgdwMenuByPos[m_dwScreen][wID-IDM_MENUITEM0])
  1098. {
  1099. case EXIT_DEX:
  1100. case FINISH_DEX:
  1101. PostQuitMessage(0);
  1102. fRetVal = TRUE;
  1103. break;
  1104. case BACK_DEX:
  1105. OnChangeScreen(-1);
  1106. fRetVal = TRUE;
  1107. break;
  1108. case NEXT_DEX:
  1109. OnNextButton();
  1110. OnChangeScreen(+1);
  1111. fRetVal = TRUE;
  1112. break;
  1113. case RADIO_1_DEX:
  1114. m_fDynamicUpdate = TRUE;
  1115. _DrawMenuIcons(FALSE);
  1116. break;
  1117. case RADIO_0_DEX:
  1118. m_fDynamicUpdate = FALSE;
  1119. _DrawMenuIcons(FALSE);
  1120. break;
  1121. case LINK_DEX:
  1122. {
  1123. TCHAR szLinkBuffer[256];
  1124. LoadStringAuto( m_hInstance, IDS_LINK, szLinkBuffer, ARRAYSIZE(szLinkBuffer) );
  1125. ShellExecute(m_hwnd, NULL, szLinkBuffer, NULL, NULL, SW_SHOWNORMAL);
  1126. }
  1127. break;
  1128. }
  1129. break;
  1130. }
  1131. return fRetVal;
  1132. }
  1133. LRESULT CDlgApp::OnQueryNewPalette()
  1134. {
  1135. if ( m_hpal )
  1136. {
  1137. HDC hdc = GetDC(m_hwnd);
  1138. if (hdc)
  1139. {
  1140. HPALETTE hpalOld = SelectPalette(hdc, m_hpal, FALSE);
  1141. UnrealizeObject(m_hpal);
  1142. RealizePalette(hdc);
  1143. UpdateWindow(m_hwnd);
  1144. if(hpalOld)
  1145. SelectPalette(hdc, hpalOld, FALSE);
  1146. ReleaseDC(m_hwnd, hdc);
  1147. }
  1148. return TRUE;
  1149. }
  1150. return FALSE;
  1151. }
  1152. LRESULT CDlgApp::OnPaletteChanged(HWND hwnd)
  1153. {
  1154. if ( m_hpal && (m_hwnd != hwnd) )
  1155. {
  1156. HDC hdc = GetDC(m_hwnd);
  1157. if (hdc)
  1158. {
  1159. HPALETTE hpalOld = SelectPalette(hdc, m_hpal, FALSE);
  1160. RealizePalette(hdc);
  1161. UpdateColors(hdc);
  1162. if (hpalOld)
  1163. SelectPalette(hdc, hpalOld, FALSE);
  1164. ReleaseDC(m_hwnd, hdc);
  1165. }
  1166. }
  1167. return TRUE;
  1168. }
  1169. LRESULT CDlgApp::OnDrawItem(UINT iCtlID, LPDRAWITEMSTRUCT pdis)
  1170. {
  1171. UINT dex = iCtlID - IDM_MENUITEM0;
  1172. RECT rect = pdis->rcItem;
  1173. POINT rectAbs = m_f8by6 ? rgPtIconText[dex] : rgPtIconText640[dex];
  1174. HPALETTE hpalOld = NULL;
  1175. TCHAR szBuffer[256];
  1176. SIZE size;
  1177. LoadString(m_hInstance, rgdwLabel[rgdwMenuByPos[m_dwScreen][dex]], szBuffer, ARRAYSIZE(szBuffer));
  1178. INT iLogPixelSx = GetDeviceCaps(pdis->hDC, LOGPIXELSX);
  1179. INT iLogPixelSy = GetDeviceCaps(pdis->hDC, LOGPIXELSY);
  1180. GetTextExtentPoint32(pdis->hDC, szBuffer, lstrlen(szBuffer), &size);
  1181. size.cx = (size.cx * iLogPixelSx) / 80;
  1182. size.cy = (size.cy * iLogPixelSy) / 80;
  1183. if ( m_hpal )
  1184. {
  1185. hpalOld = SelectPalette(pdis->hDC, m_hpal, FALSE);
  1186. RealizePalette(pdis->hDC);
  1187. }
  1188. if (LINK_DEX == rgdwMenuByPos[m_dwScreen][dex] ||
  1189. RADIO_1_DEX == rgdwMenuByPos[m_dwScreen][dex] ||
  1190. RADIO_0_DEX == rgdwMenuByPos[m_dwScreen][dex])
  1191. {
  1192. FillRect(pdis->hDC, &rect, m_hbrCenter);
  1193. }
  1194. else if (m_f8by6 && !m_fLowColor)
  1195. {
  1196. BitBlt(pdis->hDC, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, m_hdcGradientBottom, rectAbs.x, rectAbs.y - m_cyBottomPanel, SRCCOPY);
  1197. }
  1198. else if (m_f8by6 && m_fLowColor && (m_iColors > 16))
  1199. {
  1200. BitBlt(pdis->hDC, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, m_hdcGradientBottom256, rectAbs.x, rectAbs.y - m_cyBottomPanel, SRCCOPY);
  1201. }
  1202. else
  1203. {
  1204. FillRect(pdis->hDC, &rect, m_hbrPanel);
  1205. }
  1206. SetBkMode(pdis->hDC, TRANSPARENT);
  1207. SetTextColor(pdis->hDC,m_crNormalText);
  1208. UINT nFormat = DT_NOCLIP | DT_WORDBREAK;
  1209. if (BACK_DEX == rgdwMenuByPos[m_dwScreen][dex] ||
  1210. NEXT_DEX == rgdwMenuByPos[m_dwScreen][dex] ||
  1211. EXIT_DEX == rgdwMenuByPos[m_dwScreen][dex] ||
  1212. FINISH_DEX == rgdwMenuByPos[m_dwScreen][dex])
  1213. {
  1214. nFormat |= DT_RIGHT;
  1215. }
  1216. DrawText(pdis->hDC, szBuffer,-1, &rect, nFormat);
  1217. if ( pdis->itemState & ODS_FOCUS )
  1218. {
  1219. if ( m_fHighContrast )
  1220. {
  1221. rect.left -= 1;
  1222. rect.top -= 2;
  1223. rect.right += 1;
  1224. rect.bottom -= 2;
  1225. DrawFocusRect(pdis->hDC,&rect);
  1226. }
  1227. }
  1228. if ( hpalOld )
  1229. {
  1230. SelectPalette(pdis->hDC, hpalOld, FALSE);
  1231. }
  1232. _DrawMenuIcons(FALSE);
  1233. return TRUE;
  1234. }
  1235. LRESULT CALLBACK CDlgApp::s_ButtonWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1236. {
  1237. CDlgApp *pThis = (CDlgApp *)GetWindowLongPtr(GetParent(hwnd), GWLP_USERDATA);
  1238. int iID = ((int)GetWindowLongPtr(hwnd, GWLP_ID)) - IDM_MENUITEM0;
  1239. switch (uMsg)
  1240. {
  1241. case WM_ERASEBKGND:
  1242. return TRUE;
  1243. break;
  1244. case WM_MOUSEMOVE:
  1245. if (GetForegroundWindow() == GetParent(hwnd))
  1246. {
  1247. int iCurrDex = rgdwMenuByPos[pThis->m_dwScreen][iID];
  1248. if ( iCurrDex != pThis->m_iSelectedItem )
  1249. {
  1250. SetFocus(hwnd);
  1251. }
  1252. }
  1253. else
  1254. {
  1255. return FALSE;
  1256. }
  1257. break;
  1258. case WM_SETFOCUS:
  1259. if (GetForegroundWindow() == GetParent(hwnd))
  1260. {
  1261. int iCurrDex = rgdwMenuByPos[pThis->m_dwScreen][iID];
  1262. if (EMPTY != iCurrDex &&
  1263. pThis->m_iSelectedItem != iCurrDex)
  1264. {
  1265. pThis->m_iSelectedItem = iCurrDex;
  1266. SetFocus(GetDlgItem(GetParent(hwnd), IDM_MENUITEM0+iID));
  1267. }
  1268. }
  1269. else
  1270. {
  1271. return FALSE;
  1272. }
  1273. break;
  1274. }
  1275. return CallWindowProc(g_fnBtnProc, hwnd, uMsg, wParam, lParam);
  1276. }
  1277. LRESULT CALLBACK CDlgApp::s_WaitWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1278. {
  1279. switch (uMsg)
  1280. {
  1281. case WM_INITDIALOG:
  1282. SetTimer(hwnd, WAITTIMER, 10000, NULL);
  1283. return TRUE;
  1284. break;
  1285. case WM_TIMER:
  1286. if (WAITTIMER == wParam)
  1287. {
  1288. PostMessage(GetParent(hwnd), WM_SETFOCUS, NULL, NULL);
  1289. DestroyWindow(hwnd);
  1290. return TRUE;
  1291. }
  1292. break;
  1293. }
  1294. return DefWindowProc(hwnd, uMsg, wParam, lParam);
  1295. }