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.

1355 lines
38 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 "autorun.h"
  19. #include "dlgapp.h"
  20. #include "dataitem.h"
  21. #include "resource.h"
  22. WNDPROC g_fnBtnProc; // the window proc for a button.
  23. //////////////////////////////////////////////////////////////////////////
  24. // #defines
  25. //////////////////////////////////////////////////////////////////////////
  26. // todo: generate these dynamically
  27. #define FLAG_HEIGHT 43
  28. #define FLAG_WIDTH 47
  29. #define HEADER_HEIGHT 48
  30. #define HEADER_WIDTH 48
  31. #define MENUICON_HEIGHT 29
  32. #define MENUICON_WIDTH 28
  33. //////////////////////////////////////////////////////////////////////////
  34. // Code
  35. //////////////////////////////////////////////////////////////////////////
  36. typedef DWORD (WINAPI *PFNGETLAYOUT)(HDC); // gdi32!GetLayout
  37. typedef DWORD (WINAPI *PFNSETLAYOUT)(HDC, DWORD); // gdi32!SetLayout
  38. /**
  39. * This method is our contstructor for our class. It initialize all
  40. * of the instance data.
  41. */
  42. CDlgApp::CDlgApp()
  43. {
  44. m_fTaskRunning = FALSE;
  45. m_iSelectedItem = -1;
  46. g_fnBtnProc = NULL;
  47. m_hInstance = NULL;
  48. m_hwnd = NULL;
  49. m_fHighContrast = FALSE;
  50. m_hfontTitle = NULL;
  51. m_hfontHeader = NULL;
  52. m_hfontMenu = NULL;
  53. m_hbrTopPanel = NULL;
  54. m_hbrCenterPanel = NULL;
  55. m_hbrBottomPanel = NULL;
  56. m_szTitle[0] = NULL;
  57. m_szHeader[0] = NULL;
  58. // store desktop width
  59. RECT rcDesktop;
  60. SystemParametersInfo(SPI_GETWORKAREA,0, &rcDesktop, FALSE);
  61. m_cDesktopWidth = rcDesktop.right - rcDesktop.left;
  62. m_cDesktopHeight = rcDesktop.bottom - rcDesktop.top;
  63. if (m_cDesktopWidth >= 800)
  64. {
  65. m_f8by6 = TRUE;
  66. }
  67. else
  68. {
  69. m_f8by6 = FALSE;
  70. }
  71. m_hdcFlag = NULL;
  72. m_hdcHeader = NULL;
  73. m_hdcHeaderSub = NULL;
  74. m_hdcGradientTop = NULL;
  75. m_hdcGradientTop256 = NULL;
  76. m_hdcGradientBottom = NULL;
  77. m_hdcGradientBottom256 = NULL;
  78. m_hdcCloudsFlag = NULL;
  79. m_hdcCloudsFlag256 = NULL;
  80. m_hdcCloudsFlagRTL = NULL;
  81. m_hdcCloudsFlagRTL256 = NULL;
  82. for (int i = 0; i < ARRAYSIZE(m_rghdcArrows); i++)
  83. {
  84. for (int j = 0; j < ARRAYSIZE(m_rghdcArrows[0]); j++)
  85. {
  86. for (int k = 0; k < ARRAYSIZE(m_rghdcArrows[0][0]); k++)
  87. {
  88. m_rghdcArrows[i][j][k] = NULL;
  89. }
  90. }
  91. }
  92. m_hcurHand = NULL;
  93. m_dwScreen = SCREEN_MAIN;
  94. m_fLowColor = FALSE;
  95. m_iColors = -1;
  96. m_hpal = NULL;
  97. }
  98. CDlgApp::~CDlgApp()
  99. {
  100. DeleteObject(m_hfontTitle);
  101. DeleteObject(m_hfontHeader);
  102. DeleteObject(m_hfontMenu);
  103. DeleteObject(m_hbrTopPanel);
  104. DeleteObject(m_hbrCenterPanel);
  105. DeleteObject(m_hbrBottomPanel);
  106. DeleteDC(m_hdcFlag);
  107. DeleteDC(m_hdcHeader);
  108. DeleteDC(m_hdcHeaderSub);
  109. DeleteDC(m_hdcGradientTop);
  110. DeleteDC(m_hdcGradientTop256);
  111. DeleteDC(m_hdcGradientBottom);
  112. DeleteDC(m_hdcGradientBottom256);
  113. DeleteDC(m_hdcCloudsFlag);
  114. DeleteDC(m_hdcCloudsFlag256);
  115. DeleteDC(m_hdcCloudsFlagRTL);
  116. DeleteDC(m_hdcCloudsFlagRTL256);
  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. DeleteDC(m_rghdcArrows[i][j][k]);
  124. }
  125. }
  126. }
  127. }
  128. /**
  129. * This method will register our window class for the application.
  130. *
  131. * @param hInstance The application instance handle.
  132. *
  133. * @return No return value.
  134. */
  135. void CDlgApp::Register(HINSTANCE hInstance)
  136. {
  137. WNDCLASS wndclass;
  138. m_hInstance = hInstance;
  139. wndclass.style = CS_OWNDC | CS_DBLCLKS;
  140. wndclass.lpfnWndProc = s_WndProc;
  141. wndclass.cbClsExtra = 0;
  142. wndclass.cbWndExtra = 0;
  143. wndclass.hInstance = hInstance;
  144. wndclass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WEBAPP));
  145. wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
  146. wndclass.hbrBackground = NULL;
  147. wndclass.lpszMenuName = NULL;
  148. wndclass.lpszClassName = WINDOW_CLASS;
  149. RegisterClass(&wndclass);
  150. }
  151. /**
  152. * This method will initialize the data object.
  153. *
  154. * @return No return value.
  155. */
  156. BOOL CDlgApp::InitializeData(LPSTR pszCommandLine)
  157. {
  158. // Determine if we should use Direct Animaiton to display our intro graphics.
  159. // We don't use DA on slow machines, machines with less than 256 color displays,
  160. // and hydra terminals. For everything else we use DA.
  161. HWND hwnd = GetDesktopWindow();
  162. HDC hdc = GetDC( hwnd );
  163. m_iColors = GetDeviceCaps( hdc, NUMCOLORS );
  164. m_fLowColor = ((m_iColors != -1) && (m_iColors <= 256));
  165. if ( m_fLowColor )
  166. {
  167. m_hpal = CreateHalftonePalette(hdc);
  168. }
  169. // Initialize the items from the INI file.
  170. if ( !m_DataSrc.Init(pszCommandLine) )
  171. {
  172. // this is a sign from the data source that we should exit
  173. return FALSE;
  174. }
  175. // Are we in accesibility mode? This call won't work on NT 4.0 because this flag wasn't known.
  176. HIGHCONTRAST hc;
  177. hc.cbSize = sizeof(HIGHCONTRAST);
  178. hc.dwFlags = 0; // avoid random result should SPI fail
  179. if ( SystemParametersInfo( SPI_GETHIGHCONTRAST, sizeof(HIGHCONTRAST), &hc, 0 ) )
  180. {
  181. m_fHighContrast = ( hc.dwFlags & HCF_HIGHCONTRASTON );
  182. }
  183. else
  184. {
  185. // we must be on NT 4.0 or below. Just assume we aren't in high contrast mode.
  186. ASSERT( FALSE == m_fHighContrast );
  187. }
  188. // 210679: go to HighContrast mode if we're in 16-color mode as well
  189. if ( m_fLowColor && (m_iColors <= 16))
  190. {
  191. m_fHighContrast = TRUE;
  192. }
  193. // Set the color table based on our HighContrast mode setting.
  194. _SetColorTable();
  195. // create the fonts that we need to use.
  196. _CreateFonts(hdc);
  197. // create the images
  198. _CreateBitmaps();
  199. _CreateArrowBitmaps();
  200. _CreateGradientBitmaps();
  201. // load the resource strings that we always need
  202. LoadStringAuto( m_hInstance, IDS_TITLE, m_szTitle, ARRAYSIZE(m_szTitle) );
  203. LoadStringAuto( m_hInstance, IDS_HEADER, m_szHeader, ARRAYSIZE(m_szHeader) );
  204. m_hcurHand = LoadCursor( m_hInstance, MAKEINTRESOURCE(IDC_BRHAND) );
  205. ReleaseDC( hwnd, hdc );
  206. return TRUE;
  207. }
  208. #define CENTER_RGB_VALUES RGB(90,126,220)
  209. #define PANEL_RGB_VALUES RGB(59,52,177)
  210. #define TITLE_RGB_VALUES RGB(255, 255, 255)
  211. #define HEADER_RGB_VALUES RGB(214, 223, 245)
  212. #define SHADOW_RGB_VALUES RGB(52, 98, 189)
  213. #define TEXT_RGB_VALUES RGB(255, 255, 255)
  214. #define DISABLED_RGB_VALUES RGB(128, 128, 128)
  215. BOOL CDlgApp::_SetColorTable()
  216. {
  217. if ( m_fHighContrast )
  218. {
  219. // set to high contrast values
  220. m_hbrTopPanel = (HBRUSH)(COLOR_BTNFACE+1);
  221. m_hbrCenterPanel = (HBRUSH)(COLOR_WINDOW+1);
  222. m_hbrBottomPanel = (HBRUSH)(COLOR_BTNFACE+1);
  223. m_crNormalText = GetSysColor(COLOR_WINDOWTEXT);
  224. m_crTitleText = m_crNormalText;
  225. m_crHeaderText = m_crNormalText;
  226. m_crDisabledText = GetSysColor(COLOR_GRAYTEXT);
  227. m_crCenterPanel = GetSysColor(COLOR_WINDOW);
  228. m_crBottomPanel = GetSysColor(COLOR_WINDOW);
  229. }
  230. else
  231. {
  232. m_crTitleText = TITLE_RGB_VALUES;
  233. m_crHeaderText = HEADER_RGB_VALUES;
  234. m_crShadow = SHADOW_RGB_VALUES;
  235. m_crNormalText = TEXT_RGB_VALUES;
  236. m_crDisabledText = DISABLED_RGB_VALUES;
  237. m_crCenterPanel = CENTER_RGB_VALUES;
  238. m_crBottomPanel = PANEL_RGB_VALUES;
  239. if ( m_fLowColor )
  240. {
  241. HBITMAP hbmp;
  242. hbmp = (HBITMAP)LoadImage(m_hInstance, MAKEINTRESOURCE(IDB_TOP), IMAGE_BITMAP, 0,0, LR_CREATEDIBSECTION);
  243. if (hbmp)
  244. {
  245. m_hbrTopPanel = CreatePatternBrush(hbmp);
  246. DeleteObject(hbmp);
  247. }
  248. else
  249. m_hbrTopPanel = (HBRUSH)(COLOR_BTNFACE+1);
  250. hbmp = (HBITMAP)LoadImage(m_hInstance, MAKEINTRESOURCE(IDB_BOTTOM), IMAGE_BITMAP, 0,0, LR_CREATEDIBSECTION);
  251. if (hbmp)
  252. {
  253. m_hbrBottomPanel = CreatePatternBrush(hbmp);
  254. DeleteObject(hbmp);
  255. }
  256. else
  257. m_hbrBottomPanel = (HBRUSH)(COLOR_BTNFACE+1);
  258. hbmp = (HBITMAP)LoadImage(m_hInstance, MAKEINTRESOURCE(IDB_CENTER), IMAGE_BITMAP, 0,0, LR_CREATEDIBSECTION);
  259. if (hbmp)
  260. {
  261. m_hbrCenterPanel = CreatePatternBrush(hbmp);
  262. DeleteObject(hbmp);
  263. }
  264. else
  265. m_hbrCenterPanel = (HBRUSH)(COLOR_WINDOW+1);
  266. }
  267. else
  268. {
  269. m_hbrTopPanel = CreateSolidBrush( PANEL_RGB_VALUES );
  270. m_hbrCenterPanel = CreateSolidBrush( CENTER_RGB_VALUES );
  271. m_hbrBottomPanel= CreateSolidBrush ( PANEL_RGB_VALUES );
  272. }
  273. }
  274. return TRUE;
  275. }
  276. // this is called once for each font that matches the fonts we care about
  277. int CALLBACK FoundFont
  278. (
  279. ENUMLOGFONTEX *lpelfe, // logical-font data
  280. NEWTEXTMETRICEX *lpntme, // physical-font data
  281. DWORD FontType, // type of font
  282. LPARAM lParam // application-defined data
  283. )
  284. {
  285. *((BOOL*)lParam) = TRUE;
  286. return 0;
  287. }
  288. BOOL CDlgApp::_CreateFonts(HDC hdc)
  289. {
  290. #define RGFONTDEX_LARGE 0
  291. #define RGFONTDEX_SMALL 1
  292. #define RGFONTDEX_TITLE 0
  293. #define RGFONTDEX_HEADER 1
  294. #define RGFONTDEX_MENU 2
  295. #define RGFONTDEX_FULL 0
  296. #define RGFONTDEX_BACKUP 1
  297. // [in] array of IDs, arranged by {title, header, menu} x { nice font, backup font}
  298. const int rgFontID[3][2] =
  299. {{IDS_FONTFACE_TITLE, IDS_FONTFACE_TITLE_BACKUP},
  300. {IDS_FONTFACE_HEADER,IDS_FONTFACE_HEADER_BACKUP},
  301. {IDS_FONTFACE_MENU, IDS_FONTFACE_MENU_BACKUP}};
  302. // [in] array of heights, arranged by {large x small} x {title, header, menu} x { nice font, backup font}
  303. const int rgFontHeight[2][3][2] =
  304. {{{IDS_FONTCY_TITLE, IDS_FONTCY_TITLE_BACKUP},
  305. {IDS_FONTCY_HEADER, IDS_FONTCY_HEADER_BACKUP},
  306. {IDS_FONTCY_MENU, IDS_FONTCY_MENU_BACKUP}},
  307. {{IDS_FONTCY_TITLE_LIL, IDS_FONTCY_TITLE_BACKUP_LIL},
  308. {IDS_FONTCY_HEADER_LIL, IDS_FONTCY_HEADER_BACKUP_LIL},
  309. {IDS_FONTCY_MENU_LIL, IDS_FONTCY_MENU_BACKUP_LIL}}};
  310. // [out] array of pointers to the fonts
  311. HFONT* rgpFont[3] = {&m_hfontTitle, &m_hfontHeader, &m_hfontMenu};
  312. // [out] array of pointers heights of each font
  313. int* rgpcyFont[3] = {&m_cTitleFontHeight, &m_cHeaderFontHeight, &m_cMenuFontHeight};
  314. LOGFONT lf;
  315. CHARSETINFO csInfo;
  316. TCHAR szFontSize[6];
  317. for (int i = 0; i < ARRAYSIZE(rgpFont); i++)
  318. {
  319. memset(&lf,0,sizeof(lf));
  320. lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
  321. lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  322. lf.lfQuality = DEFAULT_QUALITY;
  323. lf.lfPitchAndFamily = DEFAULT_PITCH|FF_SWISS;
  324. LoadStringAuto( m_hInstance, rgFontID[i][RGFONTDEX_FULL], lf.lfFaceName, ARRAYSIZE(lf.lfFaceName) );
  325. // Set charset
  326. if (TranslateCharsetInfo((DWORD*)IntToPtr(GetACP()), &csInfo, TCI_SRCCODEPAGE) == 0)
  327. {
  328. csInfo.ciCharset = 0;
  329. }
  330. lf.lfCharSet = (BYTE)csInfo.ciCharset;
  331. // TODO: If user has accesibility large fonts turned on then scale the font sizes.
  332. LoadStringAuto( m_hInstance, rgFontHeight[m_f8by6 ? 0 : 1][i][RGFONTDEX_FULL], szFontSize, ARRAYSIZE(szFontSize) );
  333. *(rgpcyFont[i]) = MulDiv((_ttoi(szFontSize)), GetDeviceCaps(hdc, LOGPIXELSY), 72);
  334. lf.lfHeight = -(*(rgpcyFont[i]));
  335. BOOL fFound = FALSE;
  336. EnumFontFamiliesEx(hdc, &lf, (FONTENUMPROC)FoundFont, (LPARAM)&fFound, 0);
  337. if (!fFound)
  338. {
  339. LoadStringAuto( m_hInstance, rgFontID[i][RGFONTDEX_BACKUP], lf.lfFaceName, ARRAYSIZE(lf.lfFaceName) );
  340. LoadStringAuto( m_hInstance, rgFontHeight[m_f8by6 ? 0 : 1][i][RGFONTDEX_BACKUP], szFontSize, ARRAYSIZE(szFontSize) );
  341. *(rgpcyFont[i]) = MulDiv((_ttoi(szFontSize)), GetDeviceCaps(hdc, LOGPIXELSY), 72);
  342. lf.lfHeight = -(*(rgpcyFont[i]));
  343. }
  344. *(rgpFont[i]) = CreateFontIndirect(&lf);
  345. }
  346. return TRUE;
  347. }
  348. #define BITMAPTYPE_NORMAL 0x0
  349. #define BITMAPTYPE_LOWCOLOR 0x1
  350. BOOL CDlgApp::_CreateBitmaps()
  351. {
  352. const int rgiBitmapID[3][2] = {{ IDB_FLAG, IDB_FLAG_256},
  353. { IDB_HEADER, IDB_HEADER_256} ,
  354. { IDB_HEADERSUB, IDB_HEADERSUB_256} }; // [in]
  355. HDC* rgphdc[3] = {&m_hdcFlag, &m_hdcHeader, &m_hdcHeaderSub}; // [out]
  356. int iBitmapType = (m_fLowColor) ? BITMAPTYPE_LOWCOLOR : BITMAPTYPE_NORMAL;
  357. for (int i = 0; i < ARRAYSIZE(rgphdc); i++)
  358. {
  359. HBITMAP hbm;
  360. BITMAP bm;
  361. *(rgphdc[i]) = CreateCompatibleDC(NULL);
  362. hbm = (HBITMAP)LoadImage(m_hInstance, MAKEINTRESOURCE(rgiBitmapID[i][iBitmapType]), IMAGE_BITMAP, 0,0, LR_CREATEDIBSECTION);
  363. GetObject(hbm,sizeof(bm),&bm);
  364. SelectObject( *(rgphdc[i]), hbm );
  365. }
  366. return TRUE;
  367. }
  368. BOOL CDlgApp::_CreateArrowBitmaps()
  369. {
  370. const int rgiBitmapID[2][4][3] =
  371. {{{IDB_YELLOW, IDB_YELLOW_HOVER, IDB_YELLOW_DISABLED},
  372. {IDB_RED, IDB_RED_HOVER, IDB_RED_DISABLED},
  373. {IDB_GREEN, IDB_GREEN_HOVER, IDB_GREEN_DISABLED},
  374. {IDB_BLUE, IDB_BLUE_HOVER, IDB_BLUE_DISABLED}},
  375. {{IDB_YELLOW_256, IDB_YELLOW_HOVER_256, IDB_YELLOW_DISABLED_256},
  376. {IDB_RED_256, IDB_RED_HOVER_256, IDB_RED_DISABLED_256},
  377. {IDB_GREEN_256, IDB_GREEN_HOVER_256, IDB_GREEN_DISABLED_256},
  378. {IDB_BLUE_256, IDB_BLUE_HOVER_256, IDB_BLUE_DISABLED_256}}}; // [in]
  379. for (int i = 0; i < ARRAYSIZE(m_rghdcArrows); i++)
  380. {
  381. for (int j = 0; j < ARRAYSIZE(m_rghdcArrows[0]); j++)
  382. {
  383. for (int k = 0; k < ARRAYSIZE(m_rghdcArrows[0][0]); k++)
  384. {
  385. HBITMAP hbm;
  386. BITMAP bm;
  387. m_rghdcArrows[i][j][k] = CreateCompatibleDC(NULL);
  388. hbm = (HBITMAP)LoadImage(m_hInstance, MAKEINTRESOURCE(rgiBitmapID[i][j][k]), IMAGE_BITMAP, 0,0, LR_CREATEDIBSECTION);
  389. GetObject(hbm,sizeof(bm),&bm);
  390. SelectObject( m_rghdcArrows[i][j][k], hbm );
  391. }
  392. }
  393. }
  394. return TRUE;
  395. }
  396. BOOL CDlgApp::_CreateGradientBitmaps()
  397. {
  398. const int rgiBitmapID[8] = {IDB_GRADIENT_TOP, IDB_GRADIENT_TOP_256, IDB_GRADIENT_BOTTOM, IDB_GRADIENT_BOTTOM_256, IDB_CLOUDSFLAG, IDB_CLOUDSFLAG_256, IDB_CLOUDSFLAG_RTL, IDB_CLOUDSFLAG_RTL_256}; // [in]
  399. HDC* rgphdc[8] = {&m_hdcGradientTop, &m_hdcGradientTop256, &m_hdcGradientBottom, &m_hdcGradientBottom256, &m_hdcCloudsFlag, &m_hdcCloudsFlag256, &m_hdcCloudsFlagRTL, &m_hdcCloudsFlagRTL256}; // [out]
  400. for (int i = 0; i < ARRAYSIZE(rgphdc); i++)
  401. {
  402. HBITMAP hbm;
  403. BITMAP bm;
  404. *(rgphdc[i]) = CreateCompatibleDC(NULL);
  405. hbm = (HBITMAP)LoadImage(m_hInstance, MAKEINTRESOURCE(rgiBitmapID[i]), IMAGE_BITMAP, 0,0, LR_CREATEDIBSECTION);
  406. GetObject(hbm,sizeof(bm),&bm);
  407. SelectObject( *(rgphdc[i]), hbm );
  408. }
  409. return TRUE;
  410. }
  411. BOOL CDlgApp::_GetLargestStringWidth(HDC hdc, SIZE* psize)
  412. {
  413. SIZE sCurr = {0};
  414. psize->cx = 0;
  415. psize->cy = 0;
  416. for (int i = 0; i < MAX_OPTIONS; i++)
  417. {
  418. if (GetTextExtentPoint32(hdc, m_DataSrc[i].GetTitle(), lstrlen(m_DataSrc[i].GetTitle()), &sCurr))
  419. {
  420. if (sCurr.cx > psize->cx)
  421. {
  422. memcpy(psize, &sCurr, sizeof(SIZE));
  423. }
  424. }
  425. }
  426. return (psize->cx > 0);
  427. }
  428. #define ITEMOFFSET (m_f8by6 ? 35 : 26)
  429. #define MENUITEMCX(x) (m_f8by6 ? 270 : 210)
  430. #define MENUITEMCY(x) ((m_f8by6 ? 245 : 197) + ((x - 1) * ITEMOFFSET))
  431. #define MENUEXITCX(x) (m_f8by6 ? 75 : 63)
  432. #define MENUEXITCY(x) (m_f8by6 ? 540 : 406)
  433. BOOL CDlgApp::_AdjustToFitFonts()
  434. {
  435. HDC hdc = GetDC(m_hwnd);
  436. if (hdc)
  437. {
  438. SetMapMode(hdc,MM_TEXT);
  439. // don't check for error, if these fail we're totally screwed anyway
  440. SIZE sizeLargest, sizeExit = {0};
  441. _GetLargestStringWidth(hdc, &sizeLargest);
  442. GetTextExtentPoint32(hdc, m_DataSrc[0].GetTitle(), lstrlen(m_DataSrc[0].GetTitle()), &sizeExit);
  443. for (int i=0; i < MAX_MENUITEMS; i++ )
  444. {
  445. DWORD dwType = m_DataSrc[i].m_dwType;
  446. HWND hwnd = GetDlgItem(m_hwnd, IDM_MENUITEM0+i);
  447. SIZE* psize = (i == 0) ? &sizeExit: &sizeLargest;
  448. SetWindowPos(hwnd, NULL,
  449. (i == 0) ? MENUEXITCX(i) : MENUITEMCX(i),
  450. (i == 0) ? MENUEXITCY(i) : MENUITEMCY(i),
  451. (psize->cx * 3) / 2, (psize->cy * 3) / 2, SWP_NOZORDER );
  452. }
  453. ReleaseDC(m_hwnd, hdc);
  454. }
  455. return TRUE;
  456. }
  457. #define MENUARROWCX(x) (m_f8by6 ? 232 : 177)
  458. #define MENUARROWCY(x) ((m_f8by6 ? 244 : 194) + ((x - 1) * ITEMOFFSET))
  459. #define EXITARROWCX(x) (m_f8by6 ? 42 : 32)
  460. #define EXITARROWCY(x) (m_f8by6 ? 537 : 403)
  461. #define ARROWBITMAPSTUFF(rgarrows) if (WF_DISABLED & m_DataSrc[i].m_dwFlags) { phdcBitmap = &(rgarrows[2]); } else { phdcBitmap = (m_iSelectedItem == i) ? &(rgarrows[1]) : &(rgarrows[0]); }
  462. #define EXITARROWBITMAPSTUFF(rgarrows) {phdcBitmap = (m_iSelectedItem == i) ? &(rgarrows[1]) : &(rgarrows[0]);}
  463. BOOL CDlgApp::_DrawMenuIcons(BOOL fEraseBackground)
  464. {
  465. HDC hdc = GetDC(m_hwnd);
  466. if (hdc)
  467. {
  468. for (int i=0; i< m_DataSrc.m_iItems; i++ )
  469. {
  470. RECT rect;
  471. HDC* phdcBitmap;
  472. DWORD dwType = m_DataSrc[i].m_dwType;
  473. switch (dwType)
  474. {
  475. case INSTALL_WINNT: // special
  476. ARROWBITMAPSTUFF(m_rghdcArrows[m_fLowColor ? 1 : 0][2]);
  477. break;
  478. case EXIT_AUTORUN: // exit
  479. EXITARROWBITMAPSTUFF(m_rghdcArrows[m_fLowColor ? 1 : 0][1]);
  480. break;
  481. case BACK: // back icon
  482. ARROWBITMAPSTUFF(m_rghdcArrows[m_fLowColor ? 1 : 0][0]);
  483. break;
  484. default: // normal icon for everything else
  485. ARROWBITMAPSTUFF(m_rghdcArrows[m_fLowColor ? 1 : 0][3]);
  486. break;
  487. }
  488. rect.left = (i == 0) ? (EXITARROWCX(i)) : (MENUARROWCX(i));
  489. rect.top = (i == 0) ? (EXITARROWCY(i)) : (MENUARROWCY(i));
  490. rect.right = rect.left + MENUICON_WIDTH; // arrow width
  491. rect.bottom = rect.top + MENUICON_HEIGHT; // arrow height as well
  492. BitBlt( hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, *phdcBitmap, 0,0, SRCCOPY );
  493. _InvalidateRectIntl(m_hwnd, &rect, FALSE);
  494. }
  495. ReleaseDC(m_hwnd, hdc);
  496. }
  497. // clear any old icons as well
  498. RECT rect;
  499. rect.left = MENUARROWCX(0);
  500. rect.right = rect.left + MENUICON_WIDTH; // arrow width
  501. rect.top = MENUARROWCY(0);
  502. rect.bottom = m_cyClient;
  503. _InvalidateRectIntl(m_hwnd, &rect, fEraseBackground);
  504. return TRUE;
  505. }
  506. void CDlgApp::_InvalidateRectIntl(HWND hwnd, RECT* pRect, BOOL fBackgroundClear)
  507. {
  508. RECT* pRectToUse = pRect; // default to normal case (don't flip)
  509. RECT rectRTL;
  510. if (pRect)
  511. {
  512. OSVERSIONINFO osvi;
  513. if (GetVersionEx(&osvi) &&
  514. (osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) &&
  515. Mirror_IsWindowMirroredRTL(hwnd)) // right to left on Win9X
  516. {
  517. rectRTL.top = pRect->top; rectRTL.bottom = pRect->bottom;
  518. rectRTL.right = m_cxClient - pRect->left;
  519. rectRTL.left = m_cxClient - pRect->right;
  520. pRectToUse = &rectRTL;
  521. }
  522. }
  523. InvalidateRect(hwnd, pRectToUse, fBackgroundClear);
  524. }
  525. /**
  526. * This method will create the application window.
  527. *
  528. * @return No return value.
  529. */
  530. void CDlgApp::Create(int nCmdShow)
  531. {
  532. //
  533. // load the window title from the resource.
  534. //
  535. TCHAR szTitle[MAX_PATH];
  536. LoadStringAuto(m_hInstance, IDS_TITLEBAR, szTitle, MAX_PATH);
  537. DWORD dwStyle = WS_OVERLAPPED | WS_MINIMIZEBOX | WS_CAPTION | WS_SYSMENU | WS_BORDER | WS_CLIPCHILDREN;
  538. if (m_cDesktopWidth >= 800)
  539. {
  540. m_cxClient = 800;
  541. m_cyClient = 600;
  542. }
  543. else
  544. {
  545. m_cxClient = 640;
  546. m_cyClient = 480;
  547. }
  548. m_hwnd = CreateWindowEx(
  549. WS_EX_CONTROLPARENT,
  550. WINDOW_CLASS,
  551. szTitle,
  552. dwStyle,
  553. 0,
  554. 0,
  555. m_cxClient,
  556. m_cyClient,
  557. NULL,
  558. NULL,
  559. m_hInstance,
  560. this);
  561. // set the client area to a fixed size and center the window on screen
  562. RECT rect = {0};
  563. rect.left = (m_cDesktopWidth - m_cxClient) / 2;
  564. rect.top = (m_cDesktopHeight - m_cyClient) / 2;
  565. rect.right = m_cDesktopWidth - rect.left;
  566. rect.bottom = m_cDesktopHeight - rect.top;
  567. AdjustWindowRect( &rect, dwStyle, FALSE );
  568. SetWindowPos(m_hwnd, HWND_TOP, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, 0);
  569. ShowWindow(m_hwnd, SW_SHOW);
  570. m_cxTopPanel = m_f8by6 ? 80 : 64;
  571. m_cyBottomPanel = m_f8by6 ? 501 : 381;
  572. m_DataSrc.ShowSplashScreen( m_hwnd );
  573. _InvalidateRectIntl(m_hwnd, NULL, TRUE);
  574. UpdateWindow(m_hwnd);
  575. }
  576. /**
  577. * This method is our application message loop.
  578. *
  579. * @return No return value.
  580. */
  581. void CDlgApp::MessageLoop()
  582. {
  583. MSG msg;
  584. while (GetMessage(&msg, NULL, 0, 0))
  585. {
  586. // IsDialogMessage cannot understand the concept of ownerdraw default pushbuttons. It treats
  587. // these attributes as mutually exclusive. As a result, we handle this ourselves. We want
  588. // whatever control has focus to act as the default pushbutton.
  589. if ( (WM_KEYDOWN == msg.message) && (VK_RETURN == msg.wParam) )
  590. {
  591. HWND hwndFocus = GetFocus();
  592. if ( hwndFocus )
  593. {
  594. SendMessage(m_hwnd, WM_COMMAND, MAKELONG(GetDlgCtrlID(hwndFocus), BN_CLICKED), (LPARAM)hwndFocus);
  595. }
  596. continue;
  597. }
  598. if ( IsDialogMessage(m_hwnd, &msg) )
  599. continue;
  600. TranslateMessage(&msg);
  601. DispatchMessage(&msg);
  602. }
  603. }
  604. /**
  605. * This is the window procedure for the container application. It is used
  606. * to deal with all messages to our window.
  607. *
  608. * @param hwnd Window handle.
  609. * @param msg The window message.
  610. * @param wParam Window Parameter.
  611. * @param lParam Window Parameter.
  612. *
  613. * @return LRESULT
  614. */
  615. LRESULT CALLBACK CDlgApp::s_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  616. {
  617. CDlgApp *pThis = (CDlgApp *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  618. switch(msg)
  619. {
  620. case WM_NCCREATE:
  621. {
  622. CDlgApp* pThisCreate = (CDlgApp *)(((LPCREATESTRUCT)lParam)->lpCreateParams);
  623. SetWindowLongPtr(hwnd, GWLP_USERDATA, (LRESULT)pThisCreate);
  624. }
  625. break;
  626. case WM_CREATE:
  627. return pThis->OnCreate(hwnd);
  628. case WM_DESTROY:
  629. return pThis->OnDestroy();
  630. case WM_ACTIVATE:
  631. return pThis->OnActivate(wParam);
  632. case WM_PAINT:
  633. return pThis->OnPaint((HDC)wParam);
  634. case WM_ERASEBKGND:
  635. return pThis->OnEraseBkgnd((HDC)wParam);
  636. case WM_LBUTTONUP:
  637. return pThis->OnLButtonUp(LOWORD(lParam), HIWORD(lParam), (DWORD)wParam);
  638. case WM_MOUSEMOVE:
  639. return pThis->OnMouseMove(LOWORD(lParam), HIWORD(lParam), (DWORD)wParam);
  640. case WM_SETCURSOR:
  641. return pThis->OnSetCursor((HWND)wParam, LOWORD(lParam), HIWORD(lParam));
  642. case WM_COMMAND:
  643. case WM_SYSCOMMAND:
  644. if ( pThis->OnCommand(LOWORD(wParam)) )
  645. return 0;
  646. break;
  647. case WM_DRAWITEM:
  648. return pThis->OnDrawItem((UINT)wParam, (LPDRAWITEMSTRUCT)lParam);
  649. case WM_QUERYNEWPALETTE:
  650. return pThis->OnQueryNewPalette();
  651. case WM_PALETTECHANGED:
  652. return pThis->OnPaletteChanged((HWND)wParam);
  653. case ARM_CHANGESCREEN:
  654. return pThis->OnChangeScreen((DWORD)wParam);
  655. }
  656. return DefWindowProc(hwnd, msg, wParam, lParam);
  657. }
  658. /**
  659. * This method is called on WM_CREATE.
  660. *
  661. * @param hwnd Window handle for the application.
  662. *
  663. * @return No return value.
  664. */
  665. LRESULT CDlgApp::OnCreate(HWND hwnd)
  666. {
  667. m_hwnd = hwnd;
  668. _CreateMenu();
  669. _RedrawMenu();
  670. return 0;
  671. }
  672. void CDlgApp::_CreateMenu()
  673. {
  674. // Create one window for each button. These windows will get resized and moved
  675. // after we call AdjustToFitFonts.
  676. for (int i=0; i<MAX_MENUITEMS; i++)
  677. {
  678. HWND hwnd = CreateWindowEx(
  679. 0,
  680. TEXT("BUTTON"),
  681. TEXT(""),
  682. WS_CHILD|WS_VISIBLE|WS_TABSTOP|BS_PUSHBUTTON|BS_MULTILINE|BS_OWNERDRAW,
  683. 0,0,0,0,
  684. m_hwnd,
  685. NULL,
  686. m_hInstance,
  687. NULL );
  688. SetWindowLongPtr(hwnd, GWLP_ID, IDM_MENUITEM0 + i);
  689. SendMessage(hwnd, WM_SETFONT, (WPARAM)m_hfontMenu, 0);
  690. g_fnBtnProc = (WNDPROC)SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)s_ButtonWndProc);
  691. EnableWindow(hwnd, i < m_DataSrc.m_iItems);
  692. }
  693. // Set focus to first menu item
  694. SetFocus(GetDlgItem(m_hwnd, IDM_MENUITEM1));
  695. // We created the windows with zero size, now we adjust that size to take into
  696. // account for the selected font size, etc.
  697. _AdjustToFitFonts();
  698. }
  699. void CDlgApp::_RedrawMenu()
  700. {
  701. for (int i=0; i < MAX_MENUITEMS; i++)
  702. {
  703. // setting window text only actually sets the accelerator, real drawing of text is in OnDrawItem
  704. SetWindowText(GetDlgItem(m_hwnd, IDM_MENUITEM0+i), (i < m_DataSrc.m_iItems) ? m_DataSrc[i].GetTitle() : TEXT(""));
  705. EnableWindow(GetDlgItem(m_hwnd, IDM_MENUITEM0+i), (i < m_DataSrc.m_iItems));
  706. }
  707. }
  708. /**
  709. * This method handles the WM_DESTROY message.
  710. *
  711. * @return No return value.
  712. */
  713. LRESULT CDlgApp::OnDestroy()
  714. {
  715. // Shutdown the data source.
  716. m_DataSrc.Uninit(0);
  717. // ensure this is the last message we care about
  718. SetWindowLongPtr(m_hwnd, GWLP_USERDATA, 0);
  719. PostQuitMessage(0);
  720. return 0;
  721. }
  722. LRESULT CDlgApp::OnActivate(WPARAM wParam)
  723. {
  724. return 0;
  725. }
  726. /**
  727. * This method handles the WM_PAINT message.
  728. *
  729. * @return No return value.
  730. */
  731. LRESULT CDlgApp::OnPaint(HDC hdc)
  732. {
  733. PAINTSTRUCT ps;
  734. BeginPaint(m_hwnd,&ps);
  735. EndPaint(m_hwnd,&ps);
  736. return 0;
  737. }
  738. /**
  739. * This method handles the WM_ERASEBKGND message.
  740. *
  741. * @return No return value.
  742. */
  743. LRESULT CDlgApp::OnEraseBkgnd(HDC hdc)
  744. {
  745. RECT rect;
  746. HPALETTE hpalOld = NULL;
  747. if ( m_hpal )
  748. {
  749. hpalOld = SelectPalette(hdc, m_hpal, FALSE);
  750. RealizePalette(hdc);
  751. }
  752. SetMapMode(hdc, MM_TEXT);
  753. SetBkMode(hdc, TRANSPARENT);
  754. // Draw the top pane:
  755. rect.left = 0;
  756. rect.top = 0;
  757. rect.right = m_cxClient;
  758. rect.bottom = m_cxTopPanel;
  759. if (m_f8by6 && !m_fLowColor)
  760. {
  761. BitBlt( hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, m_hdcGradientTop, 0,0, SRCCOPY );
  762. }
  763. else if (m_f8by6 && m_fLowColor && (m_iColors > 16))
  764. {
  765. BitBlt( hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, m_hdcGradientTop256, 0,0, SRCCOPY );
  766. }
  767. else
  768. {
  769. FillRect(hdc, &rect, m_hbrTopPanel);
  770. }
  771. // Draw the center pane:
  772. rect.left = 0;
  773. rect.top = m_cxTopPanel;
  774. rect.right = m_cxClient;
  775. rect.bottom = m_cyBottomPanel;
  776. FillRect(hdc, &rect, m_hbrCenterPanel);
  777. // Drag the clouds/flag bitmap
  778. if (m_f8by6)
  779. {
  780. rect.left = 0;
  781. rect.top = m_cxTopPanel;
  782. rect.right = 397;
  783. rect.bottom = m_cxTopPanel + 180;
  784. HDC hdcCloudsFlag;
  785. if (Mirror_IsWindowMirroredRTL(m_hwnd))
  786. {
  787. hdcCloudsFlag = m_fLowColor? m_hdcCloudsFlagRTL256 : m_hdcCloudsFlagRTL;
  788. }
  789. else
  790. {
  791. hdcCloudsFlag = m_fLowColor? m_hdcCloudsFlag256 : m_hdcCloudsFlag;
  792. }
  793. BitBlt( hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, hdcCloudsFlag , 0,0, SRCCOPY | NOMIRRORBITMAP);
  794. }
  795. // Draw the bottom pane:
  796. rect.left = 0;
  797. rect.top = m_cyBottomPanel;
  798. rect.right = m_cxClient;
  799. rect.bottom = m_cyClient;
  800. if (m_f8by6 && !m_fLowColor)
  801. {
  802. BitBlt( hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top + 1, m_hdcGradientBottom, 0,0, SRCCOPY );
  803. }
  804. else if (m_f8by6 && m_fLowColor && (m_iColors > 16))
  805. {
  806. BitBlt( hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top + 1, m_hdcGradientBottom256, 0,0, SRCCOPY );
  807. }
  808. else
  809. {
  810. FillRect(hdc, &rect, m_hbrBottomPanel);
  811. }
  812. // Draw the flag bitmap if in 640x480
  813. if (!m_f8by6)
  814. {
  815. rect.left = 20;
  816. rect.top = 80;
  817. rect.right = rect.left + FLAG_WIDTH;
  818. rect.bottom = rect.top + FLAG_HEIGHT;
  819. BitBlt( hdc, rect.left, rect.top, FLAG_WIDTH, FLAG_HEIGHT, m_hdcFlag, 0,0, SRCCOPY | NOMIRRORBITMAP); // don't mirror flag on RTL systems for trademark reasons
  820. }
  821. // Draw the header bitmap:
  822. _PaintHeaderBitmap();
  823. // draw menu icons
  824. _DrawMenuIcons(FALSE);
  825. // draw header text
  826. if (m_f8by6)
  827. {
  828. rect.left = 237;
  829. rect.top = 192;
  830. }
  831. else
  832. {
  833. rect.left = 197;
  834. rect.top = 142;
  835. }
  836. rect.right = rect.left + 400;
  837. rect.bottom = rect.top + m_cHeaderFontHeight;
  838. HFONT hfontOld = (HFONT)SelectObject(hdc,m_hfontHeader);
  839. if ( !m_fHighContrast )
  840. {
  841. SetTextColor(hdc,m_crShadow);
  842. DrawText(hdc,m_szHeader,-1,&rect,DT_NOCLIP|DT_WORDBREAK);
  843. }
  844. _InvalidateRectIntl(m_hwnd, &rect, FALSE);
  845. rect.left -= 2; rect.right -= 2; rect.top -= 2; rect.bottom -= 2;
  846. SetTextColor(hdc,m_crHeaderText);
  847. DrawText(hdc,m_szHeader,-1,&rect,DT_NOCLIP|DT_WORDBREAK);
  848. _InvalidateRectIntl(m_hwnd, &rect, FALSE);
  849. // draw title text
  850. if (m_f8by6)
  851. {
  852. rect.left = 97;
  853. rect.top = 118;
  854. }
  855. else
  856. {
  857. rect.left = 77;
  858. rect.top = 88;
  859. }
  860. rect.right = rect.left + 700;
  861. rect.bottom = rect.top + m_cTitleFontHeight;
  862. (HFONT)SelectObject(hdc,m_hfontTitle);
  863. if ( !m_fHighContrast )
  864. {
  865. SetTextColor(hdc,m_crShadow);
  866. DrawText(hdc,m_szTitle,-1,&rect,DT_NOCLIP|DT_WORDBREAK);
  867. }
  868. rect.left -= 2; rect.right -= 2; rect.top -= 2; rect.bottom -= 2;
  869. SetTextColor(hdc,m_crTitleText);
  870. DrawText(hdc,m_szTitle,-1,&rect,DT_NOCLIP|DT_WORDBREAK);
  871. // restore the DC to its original value
  872. SelectObject(hdc,hfontOld);
  873. if(hpalOld)
  874. SelectPalette(hdc, hpalOld, FALSE);
  875. return TRUE;
  876. }
  877. void CDlgApp::_PaintHeaderBitmap()
  878. {
  879. HDC hdc = GetDC(m_hwnd);
  880. if (hdc)
  881. {
  882. RECT rect;
  883. if (m_f8by6)
  884. {
  885. rect.left = 177;
  886. rect.top = 183;
  887. }
  888. else
  889. {
  890. rect.left = 137;
  891. rect.top = 133;
  892. }
  893. rect.right = rect.left + HEADER_WIDTH;
  894. rect.bottom = rect.top + HEADER_HEIGHT;
  895. BitBlt( hdc, rect.left, rect.top, HEADER_WIDTH, HEADER_HEIGHT, (SCREEN_MAIN == m_dwScreen) ? m_hdcHeader : m_hdcHeaderSub, 0,0, SRCCOPY );
  896. _InvalidateRectIntl(m_hwnd, &rect, FALSE);
  897. ReleaseDC(m_hwnd, hdc);
  898. }
  899. }
  900. LRESULT CDlgApp::OnMouseMove(int x, int y, DWORD fwKeys)
  901. {
  902. if (GetForegroundWindow() == m_hwnd) // only care if we have focus
  903. {
  904. POINT pt;
  905. pt.x = x;
  906. pt.y = y;
  907. for (int i=0; i<m_DataSrc.m_iItems; i++)
  908. {
  909. HWND hwnd = GetDlgItem(m_hwnd, IDM_MENUITEM0+i);
  910. RECT rect;
  911. rect.left = (i > 0) ? MENUARROWCX(i) : EXITARROWCX(i);
  912. rect.top = (i > 0) ? MENUARROWCY(i) : EXITARROWCY(i);
  913. rect.right = rect.left + MENUICON_WIDTH;
  914. rect.bottom = rect.top + MENUICON_HEIGHT;
  915. if (PtInRect(&rect, pt))
  916. {
  917. SetFocus(GetDlgItem(m_hwnd, IDM_MENUITEM0 + i));
  918. SetCursor(m_hcurHand);
  919. return 0;
  920. }
  921. }
  922. SetCursor(LoadCursor(NULL,IDC_ARROW));
  923. }
  924. return 0;
  925. }
  926. LRESULT CDlgApp::OnLButtonUp(int x, int y, DWORD fwKeys)
  927. {
  928. if (GetForegroundWindow() == m_hwnd) // only care if we have focus
  929. {
  930. POINT pt;
  931. pt.x = x;
  932. pt.y = y;
  933. for (int i=0; i<m_DataSrc.m_iItems; i++)
  934. {
  935. HWND hwnd = GetDlgItem(m_hwnd, IDM_MENUITEM0+i);
  936. RECT rect;
  937. rect.left = (i > 0) ? MENUARROWCX(i) : EXITARROWCX(i);
  938. rect.top = (i > 0) ? MENUARROWCY(i) : EXITARROWCY(i);
  939. rect.right = rect.left + MENUICON_WIDTH;
  940. rect.bottom = rect.top + MENUICON_HEIGHT;
  941. if (PtInRect(&rect, pt))
  942. {
  943. OnCommand(IDM_MENUITEM0 + i);
  944. return 0;
  945. }
  946. }
  947. }
  948. return 0;
  949. }
  950. LRESULT CDlgApp::OnSetCursor(HWND hwnd, int nHittest, int wMouseMsg)
  951. {
  952. if (GetForegroundWindow() == m_hwnd) // only care if we have focus
  953. {
  954. if ( !m_fTaskRunning )
  955. {
  956. if ( hwnd != m_hwnd )
  957. {
  958. SetCursor(m_hcurHand);
  959. return TRUE;
  960. }
  961. }
  962. SetCursor(LoadCursor(NULL,IDC_ARROW));
  963. }
  964. return TRUE;
  965. }
  966. LRESULT CDlgApp::OnChangeScreen(DWORD dwScreen)
  967. {
  968. static DWORD dwSelectedOld; // we store the last position on the main screen
  969. if (m_dwScreen != dwScreen)
  970. {
  971. m_dwScreen = dwScreen;
  972. _RedrawMenu();
  973. _DrawMenuIcons(TRUE);
  974. UpdateWindow(m_hwnd);
  975. _PaintHeaderBitmap();
  976. if (SCREEN_MAIN == dwScreen) // if switching back to main, restore selection
  977. {
  978. m_iSelectedItem = dwSelectedOld;
  979. }
  980. else // otherwise default to the first item in the selection
  981. {
  982. dwSelectedOld = m_iSelectedItem;
  983. m_iSelectedItem = 1;
  984. }
  985. SetFocus(GetDlgItem(m_hwnd, IDM_MENUITEM0 + m_iSelectedItem));
  986. }
  987. return TRUE;
  988. }
  989. LRESULT CDlgApp::OnCommand(int wID)
  990. {
  991. if ( !m_fTaskRunning )
  992. {
  993. int iNewSelectedItem = m_iSelectedItem;
  994. BOOL fRun = FALSE;
  995. switch(wID)
  996. {
  997. case IDM_MENUITEM0:
  998. PostQuitMessage( 0 );
  999. break;
  1000. case IDM_MENUITEM1:
  1001. case IDM_MENUITEM2:
  1002. case IDM_MENUITEM3:
  1003. case IDM_MENUITEM4:
  1004. case IDM_MENUITEM5:
  1005. case IDM_MENUITEM6:
  1006. case IDM_MENUITEM7:
  1007. fRun = TRUE;
  1008. m_iSelectedItem = wID - IDM_MENUITEM0;
  1009. // m_iSelectedItem should be a real menu item now, but just to make sure:
  1010. ASSERT( (m_iSelectedItem < m_DataSrc.m_iItems) && (m_iSelectedItem >= 0) );
  1011. break;
  1012. default:
  1013. // When we hit this then this isn't a message we care about. We return FALSE which
  1014. // tells our WndProc to call DefWndProc which makes everything happy.
  1015. return FALSE;
  1016. }
  1017. if ( fRun )
  1018. {
  1019. m_fTaskRunning = TRUE;
  1020. m_DataSrc.Invoke( m_iSelectedItem, m_hwnd );
  1021. m_fTaskRunning = FALSE;
  1022. }
  1023. }
  1024. else
  1025. {
  1026. // currently the only commands that are valid while another task is running are
  1027. // IDM_SHOWCHECK and anything that goes to the default handler above. Everything
  1028. // else will come to here and cause a message beep
  1029. MessageBeep(0);
  1030. }
  1031. return TRUE;
  1032. }
  1033. LRESULT CDlgApp::OnQueryNewPalette()
  1034. {
  1035. if ( m_hpal )
  1036. {
  1037. HDC hdc = GetDC(m_hwnd);
  1038. if (hdc)
  1039. {
  1040. HPALETTE hpalOld = SelectPalette(hdc, m_hpal, FALSE);
  1041. UnrealizeObject(m_hpal);
  1042. RealizePalette(hdc);
  1043. UpdateWindow(m_hwnd);
  1044. if(hpalOld)
  1045. SelectPalette(hdc, hpalOld, FALSE);
  1046. ReleaseDC(m_hwnd, hdc);
  1047. }
  1048. return TRUE;
  1049. }
  1050. return FALSE;
  1051. }
  1052. LRESULT CDlgApp::OnPaletteChanged(HWND hwnd)
  1053. {
  1054. if ( m_hpal && (m_hwnd != hwnd) )
  1055. {
  1056. HDC hdc = GetDC(m_hwnd);
  1057. if (hdc)
  1058. {
  1059. HPALETTE hpalOld = SelectPalette(hdc, m_hpal, FALSE);
  1060. RealizePalette(hdc);
  1061. UpdateColors(hdc);
  1062. if (hpalOld)
  1063. SelectPalette(hdc, hpalOld, FALSE);
  1064. ReleaseDC(m_hwnd, hdc);
  1065. }
  1066. }
  1067. return TRUE;
  1068. }
  1069. LRESULT CDlgApp::OnDrawItem(UINT iCtlID, LPDRAWITEMSTRUCT pdis)
  1070. {
  1071. int i = iCtlID - IDM_MENUITEM0;
  1072. RECT rect = pdis->rcItem;
  1073. HPALETTE hpalOld = NULL;
  1074. if ( m_hpal )
  1075. {
  1076. hpalOld = SelectPalette(pdis->hDC, m_hpal, FALSE);
  1077. RealizePalette(pdis->hDC);
  1078. }
  1079. FillRect( pdis->hDC, &rect, (i > 0) ? m_hbrCenterPanel : m_hbrBottomPanel);
  1080. if (i < m_DataSrc.m_iItems)
  1081. {
  1082. SetBkMode(pdis->hDC, TRANSPARENT);
  1083. SetTextColor(
  1084. pdis->hDC,
  1085. ((m_DataSrc[i].m_dwFlags&WF_ALTERNATECOLOR)?m_crDisabledText:m_crNormalText));
  1086. DrawText(pdis->hDC,m_DataSrc[i].GetTitle(),-1,&rect,DT_NOCLIP|DT_WORDBREAK);
  1087. if ( pdis->itemState & ODS_FOCUS )
  1088. {
  1089. if ( m_fHighContrast )
  1090. {
  1091. rect.left -= 1;
  1092. rect.top -= 2;
  1093. rect.right += 1;
  1094. rect.bottom -= 2;
  1095. DrawFocusRect(pdis->hDC,&rect);
  1096. }
  1097. }
  1098. }
  1099. if ( hpalOld )
  1100. {
  1101. SelectPalette(pdis->hDC, hpalOld, FALSE);
  1102. }
  1103. _DrawMenuIcons(FALSE);
  1104. return TRUE;
  1105. }
  1106. LRESULT CALLBACK CDlgApp::s_ButtonWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1107. {
  1108. CDlgApp *pThis = (CDlgApp *)GetWindowLongPtr(GetParent(hwnd), GWLP_USERDATA);
  1109. switch (uMsg)
  1110. {
  1111. case WM_ERASEBKGND:
  1112. return TRUE;
  1113. break;
  1114. case WM_MOUSEMOVE:
  1115. if (GetForegroundWindow() == GetParent(hwnd))
  1116. {
  1117. if ( !pThis->m_fTaskRunning )
  1118. {
  1119. int iID = ((int)GetWindowLongPtr(hwnd, GWLP_ID)) - IDM_MENUITEM0;
  1120. if ( iID != pThis->m_iSelectedItem )
  1121. {
  1122. SetFocus(hwnd);
  1123. }
  1124. }
  1125. }
  1126. else
  1127. {
  1128. return FALSE;
  1129. }
  1130. break;
  1131. case WM_SETFOCUS:
  1132. if (GetForegroundWindow() == GetParent(hwnd))
  1133. {
  1134. if ( !pThis->m_fTaskRunning )
  1135. {
  1136. int iID = ((int)GetWindowLongPtr(hwnd, GWLP_ID)) - IDM_MENUITEM0;
  1137. if ( iID != pThis->m_iSelectedItem )
  1138. {
  1139. pThis->m_iSelectedItem = iID;
  1140. SetFocus(GetDlgItem(GetParent(hwnd), IDM_MENUITEM0+iID));
  1141. }
  1142. }
  1143. }
  1144. else
  1145. {
  1146. return FALSE;
  1147. }
  1148. break;
  1149. }
  1150. return CallWindowProc(g_fnBtnProc, hwnd, uMsg, wParam, lParam);
  1151. }