|
|
//////////////////////////////////////////////////////////////////////////
//
// dlgapp.cpp
//
// This file contains the main entry point into the application and
// the implementation of the CDlgApp class.
//
// (C) Copyright 1997 by Microsoft Corporation. All rights reserved.
//
//////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <commctrl.h>
#include <shlwapi.h> // for string compare functions
#include "debug.h"
#include <tchar.h>
#pragma hdrstop
#include "dlgapp.h"
#include "resource.h"
#define WINDOW_CLASS TEXT("_BerksWin2kAutorunApp_")
//////////////////////////////////////////////////////////////////////////
// Global Data
//////////////////////////////////////////////////////////////////////////
bool g_bTaskRunning = false; // true when we have a running task open
int g_iSelectedItem = -1; //
WNDPROC g_fnBtnProc = NULL; // the window proc for a button.
//////////////////////////////////////////////////////////////////////////
// Prototypes
//////////////////////////////////////////////////////////////////////////
LONG_PTR CALLBACK ButtonWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
//////////////////////////////////////////////////////////////////////////
// Metrics
// Our metrics are constants that never change. All sizes are in pixels (as per the spec):
//////////////////////////////////////////////////////////////////////////
#define c_cyLogoImage 87 // height of the branding image.
#define c_cyFadeBar 6 // height of the color fade bar
#define c_cyBranding (c_cyLogoImage+c_cyFadeBar) // height of top region that contains our branding images and the fade bar
#define c_cxCheckTextLeftEdge 29 // width from left edge for checkbox text label
#define c_cxMenuItemPadding 10 // width from left of menu item to left of text and right of text to right of menu item
#define c_cyMenuItemPadding 5 // height from top of menu item to top of text and bottom of text to bottom of menu item
#define c_cyMenuItemSpacing 1 // gap from top of one menu item to bottom of next item
#define c_cyBarToTitlePadding 12 // vertical padding from botton of fade bar to top of title text
#define c_cyTitleToBodyPadding 6 // vertical padding from bottom of title text to top of body text
#define c_cyBodyToBottomPadding 53 // vertical padding from body of body text to bottom of client area
#define c_cxRightPanelPadding 16 // generic horizontal padding used on both edges of the right pane
// Code to ensure only one instance of a particular window is running
HANDLE CheckForOtherInstance(HINSTANCE hInstance) { TCHAR szCaption[128]; HANDLE hMutex;
LoadString(hInstance, IDS_TITLE, szCaption, 128);
// We don't want to launch autorun when winnt32 is running. The standard way
// to check for this is the following mutex, which winnt32 creates:
hMutex = OpenMutex( MUTEX_ALL_ACCESS, FALSE, TEXT("Winnt32 Is Running") );
if ( hMutex ) { // The mutex exists, this means winnt32 is running so we shouldn't.
// REVIEW: Should we try to findwindow and activate winnt32?
CloseHandle( hMutex ); return 0; }
// We create a named mutex with our window caption just as a way to check
// if we are already running autorun.exe. Only if we are the first to
// create the mutex do we continue.
hMutex = CreateMutex (NULL, FALSE, szCaption);
if ( !hMutex ) { // failed to create the mutex
return 0; } else if (GetLastError() == ERROR_ALREADY_EXISTS) { // Mutex created but by someone else, activate that window
HWND hwnd = FindWindow( WINDOW_CLASS, szCaption ); SetForegroundWindow(hwnd); CloseHandle(hMutex); return 0; }
// we are the first
return hMutex; }
/**
* This function is the main entry point into our application. * * @return int Exit code. */
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin, int nShowCmd ) { HANDLE hMutex = CheckForOtherInstance(hInstance);
if ( hMutex ) { CDlgApp dlgapp; dlgapp.Register(hInstance); if ( dlgapp.InitializeData() ) { dlgapp.Create(nShowCmd); dlgapp.MessageLoop(); }
CloseHandle(hMutex); } return 0; }
typedef DWORD (WINAPI *PFNGETLAYOUT)(HDC); // gdi32!GetLayout
typedef DWORD (WINAPI *PFNSETLAYOUT)(HDC, DWORD); // gdi32!SetLayout
/**
* This function gets the DC layout. * * @return DWORD DC layout. */ DWORD Mirror_GetLayout( HDC hdc ) { DWORD dwRet=0; static PFNGETLAYOUT pfnGetLayout=NULL; static BOOL bTriedToLoadBefore = FALSE;
if( (NULL == pfnGetLayout) && !bTriedToLoadBefore) { HMODULE hmod = GetModuleHandleA("GDI32");
if( hmod ) pfnGetLayout = (PFNGETLAYOUT)GetProcAddress(hmod, "GetLayout");
bTriedToLoadBefore = TRUE; }
if( pfnGetLayout ) dwRet = pfnGetLayout( hdc );
return dwRet; }
/**
* This function sets the DC layout. * * @return DWORD old DC layout. */ DWORD Mirror_SetLayout( HDC hdc , DWORD dwLayout ) { DWORD dwRet=0; static PFNSETLAYOUT pfnSetLayout=NULL; static BOOL bTriedToLoadBefore = FALSE;
if( (NULL == pfnSetLayout) && !bTriedToLoadBefore) { HMODULE hmod = GetModuleHandleA("GDI32");
if( hmod ) pfnSetLayout = (PFNSETLAYOUT)GetProcAddress(hmod, "SetLayout");
bTriedToLoadBefore = TRUE; }
if( pfnSetLayout ) dwRet = pfnSetLayout( hdc , dwLayout );
return dwRet; }
/**
* This method is our contstructor for our class. It initialize all * of the instance data. */ CDlgApp::CDlgApp() { m_hInstance = NULL; m_hwnd = NULL;
m_bHighContrast = false;
m_hfontTitle = NULL; m_hfontMenu = NULL; m_hfontBody = NULL;
m_hbrMenuItem = NULL; m_hbrMenuBorder = NULL; m_hbrRightPanel = NULL;
m_szDefTitle[0] = NULL; m_szDefBody[0] = NULL;
// In theory, all of these metrics could be adjusted to resize the window. Resizing wouldn't
// effect the paddings and spacings so these are defined above as constants. In the real
// world we are only resizing vertically to adjust for oversized content. These are more to
// allow future expansion.
m_cxClient = 478; // width of the client area
m_cyClient = 322; // This is currently the only metirc we actually adjust.
m_cxLeftPanel = 179; // width of the panel that contains the menu items.
m_hdcTop = NULL; m_hcurHand = NULL;
m_bLowColor = false; m_iColors = -1; m_hpal = NULL; }
CDlgApp::~CDlgApp() { DeleteObject(m_hfontTitle); DeleteObject(m_hfontMenu); DeleteObject(m_hfontBody);
DeleteObject(m_hbrMenuItem); DeleteObject(m_hbrMenuBorder); DeleteObject(m_hbrRightPanel);
DeleteDC(m_hdcTop); }
/**
* This method will register our window class for the application. * * @param hInstance The application instance handle. * * @return No return value. */ void CDlgApp::Register(HINSTANCE hInstance) { WNDCLASS wndclass;
m_hInstance = hInstance; wndclass.style = CS_OWNDC; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WEBAPP)); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = NULL; wndclass.lpszMenuName = NULL; wndclass.lpszClassName = WINDOW_CLASS;
RegisterClass(&wndclass); }
/**
* This method will initialize the data object. * * @return No return value. */ bool CDlgApp::InitializeData() { // Determine if we should use Direct Animaiton to display our intro graphics.
// We don't use DA on slow machines, machines with less than 256 color displays,
// and hydra terminals. For everything else we use DA.
HWND hwnd = GetDesktopWindow(); HDC hdc = GetDC( hwnd ); m_iColors = GetDeviceCaps( hdc, NUMCOLORS ); m_bLowColor = ((m_iColors != -1) && (m_iColors <= 256)); if ( m_bLowColor ) { m_hpal = CreateHalftonePalette(hdc); } ReleaseDC( hwnd, hdc );
// Initialize the items from the INI file.
if ( !m_DataSrc.Init() ) { // this is a sign from the data source that we should exit
return false; }
// Are we in accesibility mode? This call won't work on NT 4.0 because this flag wasn't known.
HIGHCONTRAST hc; hc.cbSize = sizeof(HIGHCONTRAST); hc.dwFlags = 0; // avoid random result should SPI fail
if ( SystemParametersInfo( SPI_GETHIGHCONTRAST, sizeof(HIGHCONTRAST), &hc, 0 ) ) { m_bHighContrast = ( hc.dwFlags & HCF_HIGHCONTRASTON ); } else { // we must be on NT 4.0 or below. Just assume we aren't in high contrast mode.
ASSERT( false == m_bHighContrast ); }
// Set the color table based on our HighContrast mode setting.
SetColorTable();
// create the fonts that we need to use.
CreateWelcomeFonts(hdc);
// create the image for the top region
CreateBrandingBanner();
// we pre load the background images so they draw more quickly.
LoadBkgndImages();
// load the resource strings that we always need
LoadString( m_hInstance, IDS_DEFTITLE, m_szDefTitle, ARRAYSIZE(m_szDefTitle) ); LoadString( m_hInstance, IDS_DEFBODY, m_szDefBody, ARRAYSIZE(m_szDefBody) );
m_hcurHand = LoadCursor( m_hInstance, MAKEINTRESOURCE(IDC_BRHAND) );
return true; }
BOOL CDlgApp::SetColorTable() { if ( m_bHighContrast ) { // set to high contrast values
m_hbrMenuItem = (HBRUSH)(COLOR_BTNFACE+1); m_hbrMenuBorder = (HBRUSH)(COLOR_BTNSHADOW+1); m_hbrRightPanel = (HBRUSH)(COLOR_WINDOW+1);
m_crMenuText = GetSysColor(COLOR_BTNTEXT); m_crNormalText = GetSysColor(COLOR_WINDOWTEXT); m_crTitleText = m_crNormalText; m_crSelectedText= GetSysColor(COLOR_GRAYTEXT); } else { m_crMenuText = RGB(0,0,0); m_crNormalText = RGB(0,0,0); m_crSelectedText= RGB(0x80, 0x80, 0x80); // default value for COLOR_GRAYTEXTs
m_crTitleText = RGB(51,102,153);
m_hbrRightPanel = (HBRUSH)GetStockObject( WHITE_BRUSH );
if ( m_bLowColor ) { if (m_iColors <= 16) { // Set to colors that work well in 16 color mode.
HBITMAP hbmp; hbmp = (HBITMAP)LoadImage(m_hInstance, MAKEINTRESOURCE(IDB_16MENU), IMAGE_BITMAP, 0,0, LR_CREATEDIBSECTION); if (hbmp) { m_hbrMenuItem = CreatePatternBrush(hbmp); DeleteObject(hbmp); } else m_hbrMenuItem = (HBRUSH)(COLOR_BTNFACE+1);
hbmp = (HBITMAP)LoadImage(m_hInstance, MAKEINTRESOURCE(IDB_16BORDER), IMAGE_BITMAP, 0,0, LR_CREATEDIBSECTION); if (hbmp) { m_hbrMenuBorder = CreatePatternBrush( hbmp ); DeleteObject(hbmp); } else m_hbrMenuBorder = (HBRUSH)(COLOR_BTNSHADOW+1); //
// if ( WeAreRunningOnWin95 )
// m_crMenuText = RGB(255,255,255);
} else { // Set to colors that work well in 256 color mode. Use colors from the halftone palette.
HBITMAP hbmp; hbmp = (HBITMAP)LoadImage(m_hInstance, MAKEINTRESOURCE(IDB_256MENU), IMAGE_BITMAP, 0,0, LR_CREATEDIBSECTION); if (hbmp) { m_hbrMenuItem = CreatePatternBrush(hbmp); DeleteObject(hbmp); } else m_hbrMenuItem = (HBRUSH)(COLOR_BTNFACE+1);
hbmp = (HBITMAP)LoadImage(m_hInstance, MAKEINTRESOURCE(IDB_256BORDER), IMAGE_BITMAP, 0,0, LR_CREATEDIBSECTION); if (hbmp) { m_hbrMenuBorder = CreatePatternBrush( hbmp ); DeleteObject(hbmp); } else m_hbrMenuBorder = (HBRUSH)(COLOR_BTNSHADOW+1); } } else { m_hbrMenuItem = CreateSolidBrush( RGB(166,202,240) ); m_hbrMenuBorder = CreateSolidBrush( m_crTitleText ); } }
return TRUE; }
BOOL CDlgApp::CreateWelcomeFonts(HDC hdc) { LOGFONT lf; CHARSETINFO csInfo; TCHAR szFontSize[6];
memset(&lf,0,sizeof(lf)); lf.lfWeight = FW_BOLD; lf.lfOutPrecision = OUT_DEFAULT_PRECIS; lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; lf.lfQuality = DEFAULT_QUALITY; lf.lfPitchAndFamily = DEFAULT_PITCH|FF_SWISS; LoadString( m_hInstance, IDS_FONTFACE, lf.lfFaceName, ARRAYSIZE(lf.lfFaceName) );
// Set charset
if (TranslateCharsetInfo((DWORD*)IntToPtr(GetACP()), &csInfo, TCI_SRCCODEPAGE) == 0) { csInfo.ciCharset = 0; } lf.lfCharSet = (BYTE)csInfo.ciCharset;
// TODO: If user has accesibility large fonts turned on then scale the font sizes.
LoadString( m_hInstance, IDS_CYTITLEFONT, szFontSize, ARRAYSIZE(szFontSize) ); lf.lfHeight = -_ttoi(szFontSize); m_hfontTitle = CreateFontIndirect(&lf);
LoadString( m_hInstance, IDS_CYMENUITEMFONT, szFontSize, ARRAYSIZE(szFontSize) ); lf.lfHeight = -_ttoi(szFontSize); m_hfontMenu = CreateFontIndirect(&lf);
lf.lfWeight = FW_NORMAL; LoadString( m_hInstance, IDS_CYBODYFONT, szFontSize, ARRAYSIZE(szFontSize) ); lf.lfHeight = -_ttoi(szFontSize); m_hfontBody = CreateFontIndirect(&lf);
return TRUE; }
BOOL CDlgApp::CreateBrandingBanner() { HBITMAP hbm; int iBitmap; m_hdcTop = CreateCompatibleDC(NULL); if ( m_bLowColor && (m_iColors <= 16) ) { iBitmap = IDB_BANNER16; } else { iBitmap = IDB_BANNER; }
hbm = (HBITMAP)LoadImage(m_hInstance, MAKEINTRESOURCE(iBitmap), IMAGE_BITMAP, 0,0, LR_CREATEDIBSECTION); SelectObject( m_hdcTop, hbm );
return TRUE; }
BOOL CDlgApp::LoadBkgndImages() { BITMAP bm;
for (int i=0; i<4; i++) { m_aBkgnd[i].hbm = (HBITMAP)LoadImage(m_hInstance, MAKEINTRESOURCE(IDB_BKGND0+i), IMAGE_BITMAP, 0,0, LR_CREATEDIBSECTION); // REVIEW: are all these the same size? If yes, skip this part and use a constant:
GetObject(m_aBkgnd[i].hbm,sizeof(bm),&bm); m_aBkgnd[i].cx = bm.bmWidth; m_aBkgnd[i].cy = bm.bmHeight; }
return TRUE; }
BOOL CDlgApp::AdjustToFitFonts() { RECT rect; int cyLowestBodyPoint = 0; HDC hdc = GetDC(m_hwnd);
// now based on the users prefered font size we allow these sizes to adjust slightly
HFONT hfontOld = (HFONT)SelectObject(hdc,m_hfontTitle); int iMenuItemTop = c_cyBranding; for (int i=0; i<m_DataSrc.m_iItems; i++ ) { rect.left = m_cxLeftPanel+c_cxRightPanelPadding; rect.top = c_cyBranding + c_cyBarToTitlePadding; rect.right = m_cxClient-c_cxRightPanelPadding; SelectObject(hdc,m_hfontTitle); TCHAR* pszTitle = m_DataSrc[i].GetTitle(); DrawText(hdc,pszTitle,-1,&rect,DT_CALCRECT|DT_WORDBREAK); // this computes rcLargestTitle.bottom
rect.left = m_cxLeftPanel+c_cxRightPanelPadding; rect.top = rect.bottom + c_cyTitleToBodyPadding; rect.right = m_cxClient-c_cxRightPanelPadding; SelectObject(hdc,m_hfontBody); DrawText(hdc,m_DataSrc[i].GetDescription(),-1,&rect,DT_CALCRECT|DT_WORDBREAK); // this computes rcLargestBody.bottom
if ( rect.bottom > cyLowestBodyPoint ) cyLowestBodyPoint = rect.bottom;
rect.left = c_cxMenuItemPadding; rect.top = iMenuItemTop+c_cyMenuItemPadding; rect.right = m_cxLeftPanel-c_cxMenuItemPadding; SelectObject(hdc,m_hfontMenu); DrawText(hdc,m_DataSrc[i].GetMenuName(),-1,&rect,DT_CALCRECT|DT_WORDBREAK);
HWND hwnd; hwnd = GetDlgItem(m_hwnd, IDM_MENUITEM1+i); SetWindowPos( hwnd, NULL, 0, iMenuItemTop, m_cxLeftPanel, rect.bottom + c_cyMenuItemPadding + 1 + c_cyMenuItemSpacing - iMenuItemTop, // +1 to improve centering (due to drop letters)
SWP_NOZORDER );
iMenuItemTop = rect.bottom + c_cyMenuItemPadding + 1 + c_cyMenuItemSpacing; }
// store the bottom most menu point. Needed for drawing the background rect later.
m_cyBottomOfMenuItems = iMenuItemTop;
// restore the DC to its original value
SelectObject(hdc,hfontOld);
return TRUE; }
/**
* This method will create the application window. * * @return No return value. */ void CDlgApp::Create(int nCmdShow) { //
// load the window title from the resource.
//
TCHAR szTitle[MAX_PATH]; #ifdef BUILD_OPK_VERSION
LoadString(m_hInstance, IDS_TITLE_OPK, szTitle, MAX_PATH); #else
LoadString(m_hInstance, IDS_TITLE, szTitle, MAX_PATH); #endif
DWORD dwStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_BORDER | WS_CLIPCHILDREN; m_hwnd = CreateWindowEx( WS_EX_CONTROLPARENT, WINDOW_CLASS, szTitle, dwStyle, 0, 0, 0, 0, NULL, NULL, m_hInstance, this);
// set the client area to a fixed size and center the window on screen
RECT rect; rect.left = 0; rect.top = 0; rect.right = m_cxClient; rect.bottom = m_cyClient;
AdjustWindowRect( &rect, dwStyle, FALSE ); rect.right -= rect.left; rect.bottom -= rect.top;
RECT rcDesktop; SystemParametersInfo(SPI_GETWORKAREA,0, &rcDesktop, FALSE); rect.left = (rcDesktop.left+rcDesktop.right-rect.right)/2; rect.top = (rcDesktop.top+rcDesktop.bottom-rect.bottom)/2;
SetWindowPos(m_hwnd, HWND_TOP, rect.left, rect.top, rect.right, rect.bottom, 0);
ShowWindow(m_hwnd, nCmdShow);
m_DataSrc.ShowSplashScreen( m_hwnd );
InvalidateRect(m_hwnd, NULL, TRUE); UpdateWindow(m_hwnd); }
/**
* This method is our application message loop. * * @return No return value. */ void CDlgApp::MessageLoop() { MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { // IsDialogMessage cannot understand the concept of ownerdraw default pushbuttons. It treats
// these attributes as mutually exclusive. As a result, we handle this ourselves. We want
// whatever control has focus to act as the default pushbutton.
if ( (WM_KEYDOWN == msg.message) && (VK_RETURN == msg.wParam) ) { HWND hwndFocus = GetFocus(); if ( hwndFocus ) { SendMessage(m_hwnd, WM_COMMAND, MAKELONG(GetDlgCtrlID(hwndFocus), BN_CLICKED), (LPARAM)hwndFocus); } continue; }
if ( IsDialogMessage(m_hwnd, &msg) ) continue;
TranslateMessage(&msg); DispatchMessage(&msg); } }
/**
* This is the window procedure for the container application. It is used * to deal with all messages to our window. * * @param hwnd Window handle. * @param msg The window message. * @param wParam Window Parameter. * @param lParam Window Parameter. * * @return LRESULT */ LRESULT CALLBACK CDlgApp::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { CDlgApp *web = (CDlgApp *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
switch(msg) { case WM_NCCREATE: web = (CDlgApp *)(((LPCREATESTRUCT)lParam)->lpCreateParams); SetWindowLongPtr(hwnd, GWLP_USERDATA, (LRESULT)web); break;
case WM_CREATE: return web->OnCreate(hwnd);
case WM_DESTROY: return web->OnDestroy();
case WM_ACTIVATE: return web->OnActivate(wParam);
case WM_PAINT: return web->OnPaint((HDC)wParam);
case WM_ERASEBKGND: return web->OnEraseBkgnd((HDC)wParam);
case WM_MOUSEMOVE: return web->OnMouseMove(LOWORD(lParam), HIWORD(lParam), (DWORD)wParam);
case WM_SETCURSOR: return web->OnSetCursor((HWND)wParam, LOWORD(lParam), HIWORD(lParam));
case WM_COMMAND: case WM_SYSCOMMAND: if ( web->OnCommand(LOWORD(wParam)) ) return 0; break;
case WM_DRAWITEM: return web->OnDrawItem((UINT)wParam, (LPDRAWITEMSTRUCT)lParam);
case WM_QUERYNEWPALETTE: return web->OnQueryNewPalette();
case WM_PALETTECHANGED: return web->OnPaletteChanged((HWND)wParam);
case ARM_CHANGESCREEN: return web->_OnChangeScreen(); } return DefWindowProc(hwnd, msg, wParam, lParam); }
/**
* This method is called on WM_CREATE. * * @param hwnd Window handle for the application. * * @return No return value. */ LRESULT CDlgApp::OnCreate(HWND hwnd) { m_hwnd = hwnd; _CreateMenu(); return 0; }
void CDlgApp::_CreateMenu() { // Create one window for each button. These windows will get resized and moved
// after we call AdjustToFitFonts.
m_iItems = m_DataSrc.m_iItems; for (int i=0; i<m_iItems; i++) { HWND hwnd = CreateWindowEx( 0, TEXT("BUTTON"), m_DataSrc.m_data[i].GetMenuName(), WS_CHILD|WS_VISIBLE|WS_TABSTOP|BS_PUSHBUTTON|BS_MULTILINE|BS_OWNERDRAW, 0,0,0,0, m_hwnd, NULL, m_hInstance, NULL );
if ( hwnd ) { SetWindowLongPtr(hwnd, GWLP_ID, IDM_MENUITEM1 + i); SendMessage(hwnd, WM_SETFONT, (WPARAM)m_hfontMenu, 0); g_fnBtnProc = (WNDPROC)SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)ButtonWndProc); SetFocus(GetDlgItem(m_hwnd,IDM_MENUITEM1+i)); } }
// We created the window with zero size, now we adjust that size to take into
// acount the selected font size, etc.
AdjustToFitFonts(); // Create two static text controls, one for the title and one for the body. The
// only purpose these serve is to allow screen readers to read the correct text.
}
void CDlgApp::_DestroyMenu() { for (int i=0; i<m_iItems; i++) { DestroyWindow(GetDlgItem(m_hwnd, IDM_MENUITEM1+i)); } m_iItems = 0; }
/**
* This method handles the WM_DESTROY message. * * @return No return value. */ LRESULT CDlgApp::OnDestroy() { // Shutdown the data source.
m_DataSrc.Uninit(0);
// ensure this is the last message we care about
SetWindowLongPtr(m_hwnd, GWLP_USERDATA, 0); PostQuitMessage(0);
return 0; }
LRESULT CDlgApp::OnActivate(WPARAM wParam) { // Note: we are actually checking two things, the HIWORD(wParam) must be zero (i.e. window not minimized)
// and the LOWORD(wParam) must be one of the following two values (i.e. window being activated):
if ( WA_ACTIVE == wParam || WA_CLICKACTIVE == wParam) { HWND hwnd; hwnd = GetDlgItem(m_hwnd,IDM_MENUITEM4); SetFocus(hwnd); } return 0; }
/**
* This method handles the WM_PAINT message. * * @return No return value. */ LRESULT CDlgApp::OnPaint(HDC hdc) { PAINTSTRUCT ps; BeginPaint(m_hwnd,&ps); EndPaint(m_hwnd,&ps);
return 0; }
// winver 0x0500 definition
#ifndef NOMIRRORBITMAP
#define NOMIRRORBITMAP (DWORD)0x80000000
#endif // NOMIRRORBITMAP
#ifndef LAYOUT_RTL
#define LAYOUT_RTL 0x00000001 // Right to left
#endif // LAYOUT_RTL
/**
* This method handles the WM_ERASEBKGND message. * * @return No return value. */ LRESULT CDlgApp::OnEraseBkgnd(HDC hdc) { RECT rect; HPALETTE hpalOld = NULL;
if ( m_hpal ) { hpalOld = SelectPalette(hdc, m_hpal, FALSE); RealizePalette(hdc); }
SetMapMode(hdc, MM_TEXT); SetBkMode(hdc, TRANSPARENT);
// Draw the branding area:
DWORD dwRop = SRCCOPY; if(Mirror_GetLayout(hdc) & LAYOUT_RTL) { dwRop |= NOMIRRORBITMAP; } BitBlt( hdc,0,0,m_cxClient,c_cyBranding, m_hdcTop,0,0, dwRop );
// Draw the left pane:
// fill rect for background below menu items
rect.left = 0; rect.top = m_cyBottomOfMenuItems; rect.right = m_cxLeftPanel; rect.bottom = m_cyClient; FillRect(hdc, &rect, m_hbrMenuItem);
// Draw the right pane:
// fill right pane's background
rect.left = m_cxLeftPanel; rect.top = c_cyBranding; rect.right = m_cxClient; rect.bottom = m_cyClient; FillRect(hdc, &rect, m_hbrRightPanel);
// draw background image
if ( !m_bHighContrast ) { int iImgIndex;
if ( -1 == g_iSelectedItem ) { iImgIndex = 0; } else { iImgIndex = m_DataSrc.m_data[g_iSelectedItem].GetImgIndex(); }
HDC hdcBkgnd = CreateCompatibleDC(hdc); if (hdcBkgnd) { Mirror_SetLayout(hdcBkgnd, 0); HBITMAP hbmOld = (HBITMAP)SelectObject(hdcBkgnd, m_aBkgnd[iImgIndex].hbm); BitBlt( hdc, m_cxClient-m_aBkgnd[iImgIndex].cx, m_cyClient-m_aBkgnd[iImgIndex].cy, m_aBkgnd[iImgIndex].cx, m_aBkgnd[iImgIndex].cy, hdcBkgnd,0,0, SRCCOPY ); SelectObject(hdcBkgnd,hbmOld); DeleteDC(hdcBkgnd); } }
// draw title text
rect.top = c_cyBranding + c_cyBarToTitlePadding; rect.left = m_cxLeftPanel + c_cxRightPanelPadding; rect.right = m_cxClient - c_cxRightPanelPadding; rect.bottom = m_cyClient; HFONT hfontOld = (HFONT)SelectObject(hdc,m_hfontTitle); SetTextColor(hdc,m_crTitleText); rect.top += c_cyTitleToBodyPadding + DrawText(hdc,((-1==g_iSelectedItem)?m_szDefTitle:m_DataSrc[g_iSelectedItem].GetTitle()),-1,&rect,DT_NOCLIP|DT_WORDBREAK);
// draw body text
SelectObject(hdc,m_hfontBody); SetTextColor(hdc,m_crNormalText); DrawText(hdc,((-1==g_iSelectedItem)?m_szDefBody:m_DataSrc[g_iSelectedItem].GetDescription()),-1,&rect,DT_NOCLIP|DT_WORDBREAK);
// restore the DC to its original value
SelectObject(hdc,hfontOld); if(hpalOld) SelectPalette(hdc, hpalOld, FALSE);
return TRUE; }
LRESULT CDlgApp::OnMouseMove(int x, int y, DWORD fwKeys) { // if a task is running then we leave the menu item for that task selected until that
// task finishes running instead of doing the following logic.
if ( !g_bTaskRunning ) { // Didn't move over one of our menu items, select the default text.
if (-1 != g_iSelectedItem) { g_iSelectedItem = -1; HWND hwnd = GetDlgItem(m_hwnd,IDM_MENUITEM4); SetFocus(hwnd);
InvalidateRect(m_hwnd, NULL, TRUE); } }
return 0; }
LRESULT CDlgApp::OnSetCursor(HWND hwnd, int nHittest, int wMouseMsg) { if ( !g_bTaskRunning ) { if ( hwnd != m_hwnd ) { SetCursor(m_hcurHand); return TRUE; } }
SetCursor(LoadCursor(NULL,IDC_ARROW)); return TRUE; }
LRESULT CDlgApp::_OnChangeScreen() { _DestroyMenu(); _CreateMenu(); InvalidateRect(m_hwnd, NULL, TRUE); return TRUE; }
LRESULT CDlgApp::OnCommand(int wID) { int iNewSelectedItem = g_iSelectedItem; bool bRun = false;
switch(wID) { case IDM_MENUITEM1: case IDM_MENUITEM2: case IDM_MENUITEM3: case IDM_MENUITEM4: case IDM_MENUITEM5: case IDM_MENUITEM6: case IDM_MENUITEM7: bRun = true; g_iSelectedItem = wID - IDM_MENUITEM1; // g_iSelectedItem should be a real menu item now, but just to make sure:
ASSERT( (g_iSelectedItem < m_DataSrc.m_iItems) && (g_iSelectedItem >= 0) ); break;
default: // When we hit this then this isn't a message we care about. We return FALSE which
// tells our WndProc to call DefWndProc which makes everything happy.
return FALSE; }
if ( !g_bTaskRunning ) { if ( iNewSelectedItem != g_iSelectedItem ) { InvalidateRect(m_hwnd, NULL, TRUE); }
if ( bRun ) { g_bTaskRunning = TRUE; m_DataSrc.Invoke( g_iSelectedItem, m_hwnd ); g_bTaskRunning = FALSE; } } else { // currently the only commands that are valid while another task is running are
// IDM_SHOWCHECK and anything that goes to the default handler above. Everything
// else will come to here and cause a message beep
MessageBeep(0); }
return TRUE; }
LRESULT CDlgApp::OnQueryNewPalette() { if ( m_hpal ) { HDC hdc = GetDC(m_hwnd); HPALETTE hpalOld = SelectPalette(hdc, m_hpal, FALSE); UnrealizeObject(m_hpal); RealizePalette(hdc); InvalidateRect(m_hwnd, NULL, TRUE); UpdateWindow(m_hwnd); if(hpalOld) SelectPalette(hdc, hpalOld, FALSE); ReleaseDC(m_hwnd, hdc); return TRUE; } return FALSE; }
LRESULT CDlgApp::OnPaletteChanged(HWND hwnd) { if ( m_hpal && (m_hwnd != hwnd) ) { HDC hdc = GetDC(m_hwnd); HPALETTE hpalOld = SelectPalette(hdc, m_hpal, FALSE); RealizePalette(hdc); UpdateColors(hdc); if (hpalOld) SelectPalette(hdc, hpalOld, FALSE); ReleaseDC(m_hwnd, hdc); } return TRUE; }
LRESULT CDlgApp::OnDrawItem(UINT iCtlID, LPDRAWITEMSTRUCT pdis) { RECT rect = pdis->rcItem; int i = iCtlID - IDM_MENUITEM1; HPALETTE hpalOld = NULL;
ASSERT( (i < m_DataSrc.m_iItems) && (i >= 0) );
if ( m_hpal ) { hpalOld = SelectPalette(pdis->hDC, m_hpal, FALSE); RealizePalette(pdis->hDC); }
rect.bottom -= c_cyMenuItemSpacing;
FillRect( pdis->hDC, &rect, (pdis->itemState & ODS_FOCUS)?m_hbrRightPanel:m_hbrMenuItem ); rect.top = rect.bottom; rect.bottom += c_cyMenuItemSpacing; FillRect( pdis->hDC, &rect, m_hbrMenuBorder );
rect.top = pdis->rcItem.top;
// draw menu item text
rect.left += c_cxMenuItemPadding; rect.top += c_cyMenuItemPadding; rect.right -= c_cxMenuItemPadding;
SetBkMode(pdis->hDC, TRANSPARENT); SetTextColor( pdis->hDC, ((m_DataSrc[i].m_dwFlags&WF_ALTERNATECOLOR)?m_crSelectedText: ((pdis->itemState & ODS_FOCUS)?m_crNormalText:m_crMenuText)));
DrawText(pdis->hDC,m_DataSrc[i].GetMenuName(),-1,&rect,DT_NOCLIP|DT_WORDBREAK);
if ( pdis->itemState & ODS_FOCUS ) { if ( m_bHighContrast ) { rect.left -= 1; rect.top -= 2; rect.right += 1; rect.bottom -= 2; DrawFocusRect(pdis->hDC,&rect); } }
if ( hpalOld ) { SelectPalette(pdis->hDC, hpalOld, FALSE); }
return TRUE; }
LONG_PTR CALLBACK ButtonWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { CDlgApp *web = (CDlgApp *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
switch (uMsg) { case WM_MOUSEMOVE: if ( !g_bTaskRunning ) { int iID = ((int)GetWindowLongPtr(hwnd, GWLP_ID)) - IDM_MENUITEM1; if ( iID != g_iSelectedItem ) { SetFocus(hwnd); } } break;
case WM_SETFOCUS: if ( !g_bTaskRunning ) { int iID = ((int)GetWindowLongPtr(hwnd, GWLP_ID)) - IDM_MENUITEM1; if ( iID != g_iSelectedItem ) { g_iSelectedItem = iID;
InvalidateRect(GetParent(hwnd), NULL, TRUE);
ASSERT( (g_iSelectedItem < 7) && (g_iSelectedItem >= 0) ); } } break; }
return CallWindowProc(g_fnBtnProc, hwnd, uMsg, wParam, lParam); }
|