Leaked source code of windows server 2003
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.
 
 
 
 
 
 

2115 lines
54 KiB

//
// arcdlg.cpp: Autoreconnect dialog box
// modeless dialog box for autoreconnection status
//
// Copyright Microsoft Corportation 2001
// (nadima)
//
#include "adcg.h"
#define TRC_GROUP TRC_GROUP_UI
#define TRC_FILE "arcdlg.cpp"
#include <atrcapi.h>
#include "arcdlg.h"
#include "axresrc.h"
#define TRANSPARENT_MASK_COLOR RGB(105, 139, 228)
#ifdef OS_WINCE
#define RGB_TOPBAND RGB(0, 52, 156)
#define RGB_MIDBAND RGB(49,101,206)
#endif
//
// Runtime debug flags instrumentation for 611316
//
#define ARCDLG_DEBUG_DESTROYCALLED 0x0001
#define ARCDLG_DEBUG_WMDESTROYCALLED 0x0002
#define ARCDLG_DEBUG_WMDESTROYSUCCEED 0x0004
#define ARCDLG_DEBUG_SETNULLINSTPTR 0x0008
DWORD g_dwArcDlgDebug = 0;
#define ARC_DBG_SETINFO(x) g_dwArcDlgDebug |= x;
LPTSTR
FormatMessageVArgs(LPCTSTR pcszFormat, ...)
{
LPTSTR pszOutput;
va_list argList;
va_start(argList, pcszFormat);
if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
pcszFormat,
0, 0,
reinterpret_cast<LPTSTR>(&pszOutput), 0,
&argList) == 0)
{
pszOutput = NULL;
}
va_end(argList);
return(pszOutput);
}
///////////////////////////////////////////////////////////////////////////////
//
// ARC UI base class
//
CAutoReconnectUI::CAutoReconnectUI(
HWND hwndOwner,
HINSTANCE hInst,
CUI* pUi) :
_hwndOwner(hwndOwner),
_hInstance(hInst),
_hwnd(NULL),
_pUi(pUi)
{
DC_BEGIN_FN("CAutoReconnectUI");
#ifndef OS_WINCE
_hGDI = LoadLibrary(_T("gdi32.dll"));
if (_hGDI) {
_pfnSetLayout = (PFNGDI_SETLAYOUT)GetProcAddress(_hGDI, "SetLayout");
if (!_pfnSetLayout) {
TRC_ERR((TB,_T("GetProcAddress 'SetLayout' failed: 0x%x"),
GetLastError()));
}
}
#else
_hGDI = NULL;
_pfnSetLayout = NULL;
#endif
DC_END_FN();
}
CAutoReconnectUI::~CAutoReconnectUI()
{
DC_BEGIN_FN("CAutoReconnectUI");
#ifndef OS_WINCE
if (_hGDI) {
_pfnSetLayout = NULL;
FreeLibrary(_hGDI);
_hGDI = NULL;
}
#endif
DC_END_FN();
}
//
// PaintBitmap
//
// Params: hdcDestination = HDC to paint into.
// prcDestination = RECT in HDC to paint into.
// hbmSource = HBITMAP to paint.
// prcSource = RECT from HBITMAP to paint from.
//
// Returns: <none>
//
// Purpose: Wraps blitting a bitmap.
//
// Modified from version in shell code
//
VOID
CAutoReconnectUI::PaintBitmap(
HDC hdcDestination,
const RECT* prcDestination,
HBITMAP hbmSource,
const RECT *prcSource
)
{
HDC hdcBitmap;
DC_BEGIN_FN("PaintBitmap");
hdcBitmap = CreateCompatibleDC(NULL);
if (hdcBitmap != NULL)
{
BOOL fEqualWidthAndHeight;
INT iWidthSource, iHeightSource;
INT iWidthDestination, iHeightDestination;
INT iStretchBltMode;
#ifndef OS_WINCE
DWORD dwLayout;
#endif
HBITMAP hbmSelected;
RECT rcSource;
BITMAP bitmap;
if (prcSource == NULL)
{
if (GetObject(hbmSource, sizeof(bitmap), &bitmap) == 0)
{
bitmap.bmWidth = prcDestination->right - prcDestination->left;
bitmap.bmHeight = prcDestination->bottom - prcDestination->top;
}
SetRect(&rcSource, 0, 0, bitmap.bmWidth, bitmap.bmHeight);
prcSource = &rcSource;
}
hbmSelected = static_cast<HBITMAP>(SelectObject(hdcBitmap, hbmSource));
iWidthSource = prcSource->right - prcSource->left;
iHeightSource = prcSource->bottom - prcSource->top;
iWidthDestination = prcDestination->right - prcDestination->left;
iHeightDestination = prcDestination->bottom - prcDestination->top;
fEqualWidthAndHeight = (iWidthSource == iWidthDestination) &&
(iHeightSource == iHeightDestination);
if (!fEqualWidthAndHeight) {
#ifndef OS_WINCE
iStretchBltMode = SetStretchBltMode(hdcDestination, HALFTONE);
#endif
}
else {
iStretchBltMode = 0;
}
#ifndef OS_WINCE
if (_pfnSetLayout) {
dwLayout = _pfnSetLayout(hdcDestination,
LAYOUT_BITMAPORIENTATIONPRESERVED);
}
#endif
if (!StretchBlt(hdcDestination,
prcDestination->left,
prcDestination->top,
iWidthDestination,
iHeightDestination,
hdcBitmap,
prcSource->left,
prcSource->top,
iWidthSource,
iHeightSource,
SRCCOPY)) {
TRC_ERR((TB,_T("Blt failed")));
}
#ifndef OS_WINCE
if (_pfnSetLayout) {
_pfnSetLayout(hdcDestination, dwLayout);
}
if (!fEqualWidthAndHeight) {
(int)SetStretchBltMode(hdcDestination, iStretchBltMode);
}
#endif
(HGDIOBJ)SelectObject(hdcBitmap, hbmSelected);
DeleteDC(hdcBitmap);
}
DC_END_FN();
}
VOID
CAutoReconnectUI::CenterWindow(
HWND hwndCenterOn,
INT xRatio,
INT yRatio
)
{
RECT childRect;
RECT parentRect;
DCINT xPos;
DCINT yPos;
LONG desktopX = GetSystemMetrics(SM_CXSCREEN);
LONG desktopY = GetSystemMetrics(SM_CYSCREEN);
BOOL center = TRUE;
DC_BEGIN_FN("CenterWindowOnParent");
TRC_ASSERT(_hwnd, (TB, _T("_hwnd is NULL...was it set in WM_INITDIALOG?\n")));
if (!_hwnd)
{
TRC_ALT((TB, _T("Window doesn't exist")));
DC_QUIT;
}
if (!xRatio)
{
xRatio = 2;
}
if (!yRatio)
{
yRatio = 2;
}
GetClientRect(hwndCenterOn, &parentRect);
GetWindowRect(_hwnd, &childRect);
//
// Calculate the top left - centered in the parent window.
//
xPos = ( (parentRect.right + parentRect.left) -
(childRect.right - childRect.left)) / xRatio;
yPos = ( (parentRect.bottom + parentRect.top) -
(childRect.bottom - childRect.top)) / yRatio;
//
// Constrain to the desktop
//
if (xPos < 0)
{
xPos = 0;
}
else if (xPos > (desktopX - (childRect.right - childRect.left)))
{
xPos = desktopX - (childRect.right - childRect.left);
}
if (yPos < 0)
{
yPos = 0;
}
else if (yPos > (desktopY - (childRect.bottom - childRect.top)))
{
yPos = desktopY - (childRect.bottom - childRect.top);
}
TRC_DBG((TB, _T("Set dialog position to %u %u"), xPos, yPos));
SetWindowPos(_hwnd,
NULL,
xPos, yPos,
0, 0,
SWP_NOSIZE | SWP_NOACTIVATE);
DC_EXIT_POINT:
DC_END_FN();
return;
} // CenterWindowOnParent
#ifndef ARC_MINIMAL_UI
///////////////////////////////////////////////////////////////////////////////
//
// ARC UI - Rich UI - dialog with status text and progress band
//
CAutoReconnectDlg::CAutoReconnectDlg(HWND hwndOwner,
HINSTANCE hInst,
CUI* pUi) :
CAutoReconnectUI(hwndOwner, hInst, pUi),
_fInitialized(FALSE),
_hfntTitle(NULL),
_pProgBand(NULL),
_hPalette(NULL)
{
#ifndef OS_WINCE
BOOL fUse8BitDepth = FALSE;
#else
BOOL fUse8BitDepth = TRUE;
#endif
LOGFONT logFont;
#ifndef OS_WINCE
HDC hdcScreen;
char szPixelSize[10];
#else
WCHAR szPixelSize[10];
#endif
BITMAP bitmap;
INT logPixelsY = 100;
DC_BEGIN_FN("CAutoReconnectDlg");
_nArcTimerID = 0;
_elapsedArcTime = 0;
_fContinueReconAttempts = TRUE;
#ifndef OS_WINCE
//
// Get color depth
//
hdcScreen = GetDC(NULL);
if (hdcScreen) {
fUse8BitDepth = (GetDeviceCaps(hdcScreen, BITSPIXEL) <= 8);
logPixelsY = GetDeviceCaps(hdcScreen, LOGPIXELSY);
ReleaseDC(NULL, hdcScreen);
hdcScreen = NULL;
}
#endif
//
// Load bitmaps
//
_hbmBackground = (HBITMAP)LoadImage(
_hInstance,
MAKEINTRESOURCE(fUse8BitDepth ?
IDB_ARC_BACKGROUND8 :IDB_ARC_BACKGROUND24),
IMAGE_BITMAP,
0,
0,
#ifndef OS_WINCE
LR_CREATEDIBSECTION);
#else
0);
#endif
if ((_hbmBackground != NULL) &&
(GetObject(_hbmBackground,
sizeof(bitmap), &bitmap) >= sizeof(bitmap))) {
SetRect(&_rcBackground, 0, 0, bitmap.bmWidth, bitmap.bmHeight);
}
_hbmFlag = (HBITMAP)LoadImage(
_hInstance,
MAKEINTRESOURCE(fUse8BitDepth ?
IDB_ARC_WINFLAG8 :IDB_ARC_WINFLAG24),
IMAGE_BITMAP,
0,
0,
#ifndef OS_WINCE
LR_CREATEDIBSECTION);
#else
0);
#endif
if ((_hbmFlag != NULL) &&
(GetObject(_hbmFlag,
sizeof(bitmap), &bitmap) >= sizeof(bitmap))) {
SetRect(&_rcFlag, 0, 0, bitmap.bmWidth, bitmap.bmHeight);
}
#ifndef OS_WINCE
_hbmDisconImg = (HBITMAP)LoadImage(
_hInstance,
MAKEINTRESOURCE(fUse8BitDepth ?
IDB_ARC_DISCON8 :IDB_ARC_DISCON24),
IMAGE_BITMAP,
0,
0,
LR_CREATEDIBSECTION);
if ((_hbmDisconImg != NULL) &&
(GetObject(_hbmDisconImg,
sizeof(bitmap), &bitmap) >= sizeof(bitmap))) {
SetRect(&_rcDisconImg, 0, 0, bitmap.bmWidth, bitmap.bmHeight);
}
_hPalette = CUT::UT_GetPaletteForBitmap(NULL, _hbmBackground);
#endif
//
// Create fonts. Load the font name and size from resources.
//
ZeroMemory(&logFont, sizeof(logFont));
#ifndef OS_WINCE
if (LoadStringA(_hInstance,
IDS_ARC_TITLE_FACESIZE,
szPixelSize,
sizeof(szPixelSize)) != 0)
#else
if (LoadString(_hInstance,
IDS_ARC_TITLE_FACESIZE,
szPixelSize,
sizeof(szPixelSize)/sizeof(WCHAR)) != 0)
#endif
{
#ifndef OS_WINCE
logFont.lfHeight = -MulDiv(atoi(szPixelSize),
logPixelsY, 72);
#else
logFont.lfHeight = -(_wtoi(szPixelSize)/logPixelsY*72);
#endif
if (LoadString(_hInstance,
IDS_ARC_TITLE_FACENAME,
logFont.lfFaceName,
LF_FACESIZE) != 0)
{
logFont.lfWeight = FW_BOLD;
logFont.lfQuality = DEFAULT_QUALITY;
_hfntTitle = CreateFontIndirect(&logFont);
}
}
_szConnectAttemptStringTmpl[0] = NULL;
if (!LoadString(_hInstance,
IDS_ARC_CONATTEMPTS,
_szConnectAttemptStringTmpl,
sizeof(_szConnectAttemptStringTmpl)/sizeof(TCHAR)) != 0)
{
TRC_ERR((TB,_T("Failed to load IDS_ARC_CONATTEMPTS")));
}
_lastDiscReason = NL_DISCONNECT_LOCAL;
#ifdef OS_WINCE
_hbrTopBand = CreateSolidBrush(RGB_TOPBAND);
_hbrMidBand = CreateSolidBrush(RGB_MIDBAND);
#endif
_fInitialized = (_hbmBackground &&
_hbmFlag &&
_hfntTitle &&
_pUi &&
_szConnectAttemptStringTmpl[0]);
if (!_fInitialized) {
TRC_ERR((TB,_T("Failed to properly init arc dlg")));
}
DC_END_FN();
}
CAutoReconnectDlg::~CAutoReconnectDlg()
{
if (_hbmBackground) {
DeleteObject(_hbmBackground);
_hbmBackground = NULL;
}
if (_hbmFlag) {
DeleteObject(_hbmFlag);
_hbmFlag = NULL;
}
#ifndef OS_WINCE
if (_hbmDisconImg) {
DeleteObject(_hbmDisconImg);
_hbmDisconImg = NULL;
}
#endif
if (_hfntTitle) {
DeleteObject(_hfntTitle);
_hfntTitle = NULL;
}
if (_hPalette) {
DeleteObject(_hPalette);
_hPalette = NULL;
}
if (_pProgBand) {
delete _pProgBand;
_pProgBand = NULL;
}
#ifdef OS_WINCE
if (_hbrTopBand) {
DeleteObject(_hbrTopBand);
_hbrTopBand = NULL;
}
if (_hbrMidBand) {
DeleteObject(_hbrMidBand);
_hbrMidBand = NULL;
}
#endif
}
HWND CAutoReconnectDlg::StartModeless()
{
LONG_PTR dwStyle;
DC_BEGIN_FN("StartModeless");
if (!_fInitialized) {
TRC_ERR((TB,_T("failing startmodeless fInitialized is FALSE")));
return NULL;
}
_hwnd = CreateDialogParam(_hInstance,
MAKEINTRESOURCE(IDD_ARCDLG),
_hwndOwner,
StaticDialogBoxProc,
(LPARAM)this);
if (_hwnd) {
//
// Make the dialog a child of the parent
//
dwStyle = GetWindowLongPtr(_hwnd, GWL_STYLE);
dwStyle &= ~WS_POPUP;
dwStyle |= WS_CHILD;
SetParent(_hwnd, _hwndOwner);
SetWindowLongPtr(_hwnd, GWL_STYLE, dwStyle);
}
else {
TRC_ERR((TB,_T("CreateDialog failed: 0x%x"), GetLastError()));
}
DC_END_FN();
return _hwnd;
}
BOOL CAutoReconnectDlg::ShowTopMost()
{
BOOL rc = FALSE;
DC_BEGIN_FN("ShowTopMost");
if (!_hwnd) {
DC_QUIT;
}
ShowWindow(_hwnd, SW_SHOWNORMAL);
//
// Bring the window to the TOP of the Z order
//
SetWindowPos( _hwnd,
HWND_TOPMOST,
0, 0, 0, 0,
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE );
rc = TRUE;
DC_EXIT_POINT:
DC_END_FN();
return rc;
}
VOID
CAutoReconnectDlg::OnParentSizePosChange()
{
DC_BEGIN_FN("OnParentSizePosChange");
//
// Reposition the dialog to 1/2 down the middle
// of the owner window
//
if (_hwnd && _hwndOwner) {
CenterWindow(_hwndOwner, 2, 2);
}
DC_END_FN();
}
//
// Handler for WM_ERASEBKGND (See platform sdk docs)
//
VOID
CAutoReconnectDlg::OnEraseBkgnd(
HWND hwnd,
HDC hdc
)
{
RECT rc;
HPALETTE hPaletteOld = NULL;
DC_BEGIN_FN("OnEraseBkgnd");
TRC_ASSERT(_hbmBackground, (TB,_T("_hbmBackground is NULL")));
if (GetClientRect(hwnd, &rc)) {
hPaletteOld = SelectPalette(hdc, _hPalette, FALSE);
RealizePalette(hdc);
PaintBitmap(hdc, &rc, _hbmBackground, &_rcBackground);
SelectPalette(hdc, hPaletteOld, FALSE);
RealizePalette(hdc);
}
DC_END_FN();
}
//
// Handler for WM_PRINTCLIENT
//
VOID
CAutoReconnectDlg::OnPrintClient(
HWND hwnd,
HDC hdcPrint,
DWORD dwOptions)
{
DC_BEGIN_FN("OnPrintClient");
#ifndef OS_WINCE
if ((dwOptions & (PRF_ERASEBKGND | PRF_CLIENT)) != 0)
{
OnEraseBkgnd(hwnd, hdcPrint);
}
#endif
DC_END_FN();
}
#ifndef OS_WINCE
void xDrawTransparentBitmap(HDC hdc, HBITMAP hBitmap, short xStart,
short yStart, COLORREF cTransparentColor)
{
BITMAP bm;
COLORREF cColor;
HBITMAP bmAndBack, bmAndObject, bmAndMem, bmSave;
HBITMAP bmBackOld, bmObjectOld, bmMemOld, bmSaveOld;
HDC hdcMem, hdcBack, hdcObject, hdcTemp, hdcSave;
POINT ptSize;
hdcTemp = CreateCompatibleDC(hdc);
SelectObject(hdcTemp, hBitmap); // Select the bitmap
GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
ptSize.x = bm.bmWidth; // Get width of bitmap
ptSize.y = bm.bmHeight; // Get height of bitmap
DPtoLP(hdcTemp, &ptSize, 1); // Convert from device
// to logical points
// Create some DCs to hold temporary data.
hdcBack = CreateCompatibleDC(hdc);
hdcObject = CreateCompatibleDC(hdc);
hdcMem = CreateCompatibleDC(hdc);
hdcSave = CreateCompatibleDC(hdc);
// Create a bitmap for each DC. DCs are required for a number of
// GDI functions.
// Monochrome DC
bmAndBack = CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL);
// Monochrome DC
bmAndObject = CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL);
bmAndMem = CreateCompatibleBitmap(hdc, ptSize.x, ptSize.y);
bmSave = CreateCompatibleBitmap(hdc, ptSize.x, ptSize.y);
// Each DC must select a bitmap object to store pixel data.
bmBackOld = (HBITMAP)SelectObject(hdcBack, bmAndBack);
bmObjectOld = (HBITMAP)SelectObject(hdcObject, bmAndObject);
bmMemOld = (HBITMAP)SelectObject(hdcMem, bmAndMem);
bmSaveOld = (HBITMAP)SelectObject(hdcSave, bmSave);
// Set proper mapping mode.
SetMapMode(hdcTemp, GetMapMode(hdc));
// Save the bitmap sent here, because it will be overwritten.
BitBlt(hdcSave, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCCOPY);
// Set the background color of the source DC to the color.
// contained in the parts of the bitmap that should be transparent
cColor = SetBkColor(hdcTemp, cTransparentColor);
// Create the object mask for the bitmap by performing a BitBlt
// from the source bitmap to a monochrome bitmap.
BitBlt(hdcObject, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0,
SRCCOPY);
// Set the background color of the source DC back to the original
// color.
SetBkColor(hdcTemp, cColor);
// Create the inverse of the object mask.
BitBlt(hdcBack, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0,
NOTSRCCOPY);
// Copy the background of the main DC to the destination.
BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdc, xStart, yStart,
SRCCOPY);
// Mask out the places where the bitmap will be placed.
BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0, SRCAND);
// Mask out the transparent colored pixels on the bitmap.
BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcBack, 0, 0, SRCAND);
// XOR the bitmap with the background on the destination DC.
BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCPAINT);
// Copy the destination to the screen.
BitBlt(hdc, xStart, yStart, ptSize.x, ptSize.y, hdcMem, 0, 0,
SRCCOPY);
// Place the original bitmap back into the bitmap sent here.
BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcSave, 0, 0, SRCCOPY);
// Delete the memory bitmaps.
DeleteObject(SelectObject(hdcBack, bmBackOld));
DeleteObject(SelectObject(hdcObject, bmObjectOld));
DeleteObject(SelectObject(hdcMem, bmMemOld));
DeleteObject(SelectObject(hdcSave, bmSaveOld));
// Delete the memory DCs.
DeleteDC(hdcMem);
DeleteDC(hdcBack);
DeleteDC(hdcObject);
DeleteDC(hdcSave);
DeleteDC(hdcTemp);
}
//
// Handler for WM_DRAWITEM (see platform sdk)
// Handles owner draw items
//
//
VOID
CAutoReconnectDlg::OnDrawItem(
HWND hwnd,
const DRAWITEMSTRUCT *pDIS
)
{
DC_BEGIN_FN("OnDrawItem");
HPALETTE hPaletteOld = NULL;
HFONT hfntSelected;
int iBkMode;
COLORREF colorText;
RECT rc;
SIZE size;
TCHAR szText[256];
hPaletteOld = SelectPalette(pDIS->hDC, _hPalette, FALSE);
(UINT)RealizePalette(pDIS->hDC);
switch (pDIS->CtlID)
{
case IDC_TITLE_ARCING:
{
// Draw the title of the dialog "AutoReconecting".
hfntSelected = static_cast<HFONT>(SelectObject(pDIS->hDC,
_hfntTitle));
colorText = SetTextColor(pDIS->hDC, 0x00FFFFFF);
iBkMode = SetBkMode(pDIS->hDC, TRANSPARENT);
(int)GetWindowText(GetDlgItem(hwnd, pDIS->CtlID),
szText,
sizeof(szText)/sizeof(szText[0]));
GetTextExtentPoint(pDIS->hDC, szText, lstrlen(szText), &size);
CopyRect(&rc, &pDIS->rcItem);
InflateRect(&rc, 0, -((rc.bottom - rc.top - size.cy) / 2));
DrawText(pDIS->hDC, szText, -1, &rc, 0);
SetBkMode(pDIS->hDC, iBkMode);
SetTextColor(pDIS->hDC, colorText);
SelectObject(pDIS->hDC, hfntSelected);
}
break;
case IDC_TITLE_FLAG:
{
BITMAP bitmap;
GetClientRect(pDIS->hwndItem, &rc);
if (GetObject(_hbmFlag, sizeof(bitmap), &bitmap) != 0)
{
rc.left += ((rc.right - rc.left) - bitmap.bmWidth) / 2;
rc.right = rc.left + bitmap.bmWidth;
rc.top += ((rc.bottom - rc.top) - bitmap.bmHeight) / 2;
rc.bottom = rc.top + bitmap.bmHeight;
}
PaintBitmap(pDIS->hDC, &rc, _hbmFlag, &_rcFlag);
}
break;
case IDC_ARC_STATIC_DISCBMP:
{
xDrawTransparentBitmap(pDIS->hDC, _hbmDisconImg,
0, 0,
TRANSPARENT_MASK_COLOR);
}
break;
}
(HGDIOBJ)SelectPalette(pDIS->hDC, hPaletteOld, FALSE);
(UINT)RealizePalette(pDIS->hDC);
DC_END_FN();
}
#endif
//
// StaticDialogBoxProc
// Params: see platform sdk for wndproc
//
// Delegates work to appropriate instance
//
//
INT_PTR CALLBACK
CAutoReconnectDlg::StaticDialogBoxProc(
HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
//
// Delegate to appropriate instance
// (only works for single instance dialogs)
//
DC_BEGIN_FN("StaticDialogBoxProc");
DCINT retVal = 0;
CAutoReconnectDlg* pDlg;
if(WM_INITDIALOG != uMsg) {
//
// Need to retreive the instance pointer from the window class
//
pDlg = (CAutoReconnectDlg*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
}
else {
//
// WM_INITDIALOG need to grab and set instance pointer
//
//
// lParam contains this pointer (passed in DialogBoxParam)
//
pDlg = (CAutoReconnectDlg*) lParam;
TRC_ASSERT(pDlg,(TB,_T("Got null instance pointer (lParam) in WM_INITDIALOG")));
if(!pDlg) {
DC_QUIT;
}
//
// Store the dialog pointer in the windowclass
//
SetLastError(0);
if(!SetWindowLongPtr( hwndDlg, GWLP_USERDATA, (LONG_PTR)pDlg)) {
if(GetLastError()) {
TRC_ERR((TB,_T("SetWindowLongPtr failed 0x%x"),
GetLastError()));
DC_QUIT;
}
}
}
if (pDlg) {
retVal = pDlg->DialogBoxProc(hwndDlg, uMsg, wParam, lParam);
}
DC_EXIT_POINT:
DC_END_FN();
return retVal;
}
//
// Name: DialogBoxProc
//
// Purpose: Handles AutoReconnect dialog box proc
//
// Returns: TRUE if message dealt with
// FALSE otherwise
//
// Params: See windows documentation
//
//
INT_PTR CALLBACK CAutoReconnectDlg::DialogBoxProc (HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
INT_PTR rc = FALSE;
DC_BEGIN_FN("DialogBoxProc");
switch (uMsg)
{
case WM_INITDIALOG:
{
//
// Center
//
_hwnd = hwndDlg;
CenterWindow(_hwndOwner, 2, 2);
UpdateConnectionAttempts(0, 0);
//
// The band is positioned a fixed ratio of the way
// down the height of this dialog to match up with the
// background image
//
RECT cliRect;
LONG nBandPos = 0;
GetClientRect(hwndDlg, &cliRect);
nBandPos = (INT)((cliRect.bottom - cliRect.top) * 42.0/193.0);
_pProgBand = new CProgressBand(hwndDlg,
_hInstance,
nBandPos,
IDB_ARC_BAND24,
IDB_ARC_BAND8,
NULL);
if (_pProgBand) {
if (!_pProgBand->Initialize()) {
TRC_ERR((TB,_T("Progress band failed to init")));
delete _pProgBand;
_pProgBand = NULL;
}
}
//
// Subclass the cancel button to do the correct key handling
// this is important because the message loop is driven by
// the container application so we can't just rely on it
// calling IsDialogMessage(). In other words we need to manually
// handle the appropriate keymapping code.
//
#ifndef OS_WINCE
if (!SetWindowSubclass(GetDlgItem(hwndDlg, IDCANCEL),
CancelBtnSubclassProc, IDCANCEL,
reinterpret_cast<DWORD_PTR>(this))) {
TRC_ERR((TB,_T("SetWindowSubclass failed: 0x%x"),
GetLastError()));
}
#else
_lOldCancelProc = (WNDPROC )SetWindowLong(GetDlgItem(hwndDlg, IDCANCEL),
GWL_WNDPROC, (LONG )CancelBtnSubclassProc);
SetWindowLong(GetDlgItem(hwndDlg, IDCANCEL), GWL_USERDATA, reinterpret_cast<DWORD_PTR>(this));
#endif
//
// Set the focus on the cancel button
// and make it the default button
//
SendMessage(hwndDlg, DM_SETDEFID, IDCANCEL, 0);
//SetFocus(GetDlgItem(hwndDlg, IDCANCEL));
SetFocus(hwndDlg);
if (_pProgBand) {
_pProgBand->StartSpinning();
}
rc = 1;
}
break;
case WM_COMMAND:
{
switch(DC_GET_WM_COMMAND_ID(wParam))
{
case IDCANCEL:
{
TRC_NRM((TB,_T("AutoReconnect cancel was pressed")));
if (_pProgBand) {
_pProgBand->StopSpinning();
}
_pUi->UI_UserInitiatedDisconnect(_lastDiscReason);
//
// Disable the cancel button and set the cancel flag.
// This will take effect on the next autoreconnection
// notification.
//
EnableWindow(GetDlgItem(hwndDlg, IDCANCEL), FALSE);
_fContinueReconAttempts = FALSE;
}
break;
}
}
break; //WM_COMMAND
case WM_DESTROY:
{
ARC_DBG_SETINFO(ARCDLG_DEBUG_WMDESTROYCALLED);
#ifndef OS_WINCE
RemoveWindowSubclass(GetDlgItem(hwndDlg, IDCANCEL),
CancelBtnSubclassProc, IDCANCEL);
#else
SetWindowLong(GetDlgItem(hwndDlg, IDCANCEL),
GWL_WNDPROC, (LONG )_lOldCancelProc);
#endif
//
// Clear the instance data to prevent further processing
// after the dialog is deleted
//
SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)NULL);
}
break;
#ifndef OS_WINCE
case WM_DRAWITEM:
{
OnDrawItem(hwndDlg, (DRAWITEMSTRUCT*)(lParam));
}
break;
#endif
case WM_TIMER:
{
if (_pProgBand) {
_pProgBand->OnTimer((INT)wParam);
}
}
break;
case WM_ERASEBKGND:
{
OnEraseBkgnd(hwndDlg, (HDC)wParam);
if (_pProgBand) {
_pProgBand->OnEraseParentBackground((HDC)wParam);
}
rc = 1;
}
break;
case WM_CTLCOLORDLG:
{
SetBkMode((HDC)wParam, TRANSPARENT);
rc = (INT_PTR)GetStockObject(NULL_BRUSH);
}
break;
case WM_CTLCOLORSTATIC:
{
SetTextColor((HDC)wParam, RGB(255,255,255));
SetBkMode((HDC)wParam, TRANSPARENT);
#ifndef OS_WINCE
rc = (INT_PTR)GetStockObject(NULL_BRUSH);
#else
LONG lId = GetWindowLong((HWND)lParam, GWL_ID);
rc = (INT_PTR)((lId == IDC_TITLE_ARCING) ? _hbrTopBand : _hbrMidBand);
#endif
}
break;
#ifndef OS_WINCE
case WM_PRINTCLIENT:
{
OnPrintClient(hwndDlg, (HDC)wParam, (DWORD)lParam);
rc = 1;
}
break;
#endif
default:
{
rc = 0;
}
break;
}
DC_END_FN();
return(rc);
} /* DialogBoxProc */
VOID CAutoReconnectDlg::UpdateConnectionAttempts(
ULONG conAttempts,
ULONG maxConAttempts)
{
LPTSTR szFormattedString = NULL;
HWND hwndStatic;
DC_BEGIN_FN("UpdateConnectionAttempts");
hwndStatic = GetDlgItem(GetHwnd(), IDC_ARC_STATIC_INFO);
szFormattedString = FormatMessageVArgs(
_szConnectAttemptStringTmpl,
conAttempts,
maxConAttempts
);
if (szFormattedString) {
SetDlgItemText(GetHwnd(),
IDC_ARC_STATIC_INFO,
szFormattedString);
LocalFree(szFormattedString);
//
// Invalidate the static control to trigger a repaint
//
if (hwndStatic) {
RECT rc;
if (GetWindowRect(hwndStatic, &rc)) {
MapWindowPoints(HWND_DESKTOP, GetHwnd(),
(LPPOINT)&rc,sizeof(RECT)/sizeof(POINT));
InvalidateRect(GetHwnd(), &rc, TRUE);
UpdateWindow(GetHwnd());
}
}
}
DC_END_FN();
}
//
// Called to notify us that we got disconnected
// this means the last connection attempt failed
//
// Params:
// discReason - disconnect major reason code
// attemptCount - attempt count so far
// pfContinueArc - [OUT] set to FALSE to stop ARC
//
VOID
CAutoReconnectDlg::OnNotifyAutoReconnecting(
UINT discReason,
ULONG attemptCount,
ULONG maxAttemptCount,
BOOL* pfContinueArc
)
{
DC_BEGIN_FN("OnNotifyDisconnected");
_lastDiscReason = discReason;
if (_fContinueReconAttempts) {
_connectionAttempts = attemptCount;
UpdateConnectionAttempts(attemptCount, maxAttemptCount);
}
else {
TRC_NRM((TB,_T("Stopping arc - _fContinueReconAttempts is FALSE")));
}
*pfContinueArc = _fContinueReconAttempts;
DC_END_FN();
}
//
// Called to notify us that we have connected
//
VOID CAutoReconnectDlg::OnNotifyConnected()
{
DC_BEGIN_FN("OnNotifyConnected");
_fContinueReconAttempts = FALSE;
DC_END_FN();
}
//
// Destory
// Called to kill and cleanup the dialog
//
//
BOOL
CAutoReconnectDlg::Destroy()
{
DC_BEGIN_FN("Destroy");
ARC_DBG_SETINFO(ARCDLG_DEBUG_DESTROYCALLED);
if (!DestroyWindow(_hwnd)) {
TRC_ERR((TB,_T("DestroyWindow failed: 0x%x"),
GetLastError()));
}
else {
ARC_DBG_SETINFO(ARCDLG_DEBUG_WMDESTROYSUCCEED);
}
//
// Clear the instance data to prevent further processing
// after the dialog is deleted
//
ARC_DBG_SETINFO(ARCDLG_DEBUG_SETNULLINSTPTR);
SetWindowLongPtr(_hwnd, GWLP_USERDATA, (LONG_PTR)NULL);
DC_END_FN();
return TRUE;
}
#ifndef OS_WINCE
LRESULT CALLBACK
CAutoReconnectDlg::CancelBtnSubclassProc(
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam,
UINT_PTR uiID,
DWORD_PTR dwRefData
)
#else
LRESULT CALLBACK
CAutoReconnectDlg::CancelBtnSubclassProc(
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
#endif
{
LRESULT rc = 0;
CAutoReconnectDlg* pThis = NULL;
DC_BEGIN_FN("CancelBtnSubclassProc");
#ifndef OS_WINCE
pThis = reinterpret_cast<CAutoReconnectDlg*>(dwRefData);
#else
pThis = reinterpret_cast<CAutoReconnectDlg*>(GetWindowLong(hwnd, GWL_USERDATA));
#endif
TRC_ASSERT(pThis, (TB,_T("pThis == NULL")));
switch (uMsg)
{
case WM_KEYUP:
{
//
// Hitting 'Esc' or 'Return' on the Cancel button
// are the same as pressing it
//
if (VK_ESCAPE == wParam ||
VK_RETURN == wParam) {
SendMessage(hwnd, BM_CLICK, NULL, NULL);
}
}
//
// Intentional fallthru
//
default:
{
#ifndef OS_WINCE
rc = DefSubclassProc(hwnd, uMsg, wParam, lParam);
#else
rc = CallWindowProc(pThis->_lOldCancelProc, hwnd, uMsg, wParam, lParam);
#endif
}
break;
}
DC_END_FN();
return rc;
}
#else // ARC_MINIMAL_UI
#include "res_inc.c"
CAutoReconnectPlainUI::CAutoReconnectPlainUI(HWND hwndOwner,
HINSTANCE hInst,
CUI* pUi) :
CAutoReconnectUI(hwndOwner, hInst, pUi),
_fInitialized(FALSE),
_hPalette(NULL),
_fIsUiVisible(FALSE)
{
#ifndef OS_WINCE
BOOL fUse8BitDepth = FALSE;
#else
BOOL fUse8BitDepth = TRUE;
#endif
LOGFONT logFont;
#ifndef OS_WINCE
HDC hdcScreen;
#else
#endif
BITMAP bitmap;
INT logPixelsY = 100;
DC_BEGIN_FN("CAutoReconnectPlainUI");
_nFlashingTimer = 0;
_fContinueReconAttempts = TRUE;
#ifndef OS_WINCE
//
// Get color depth
//
hdcScreen = GetDC(NULL);
if (hdcScreen) {
fUse8BitDepth = (GetDeviceCaps(hdcScreen, BITSPIXEL) <= 8);
logPixelsY = GetDeviceCaps(hdcScreen, LOGPIXELSY);
//
// Load bitmaps
//
LPBYTE pBitmapBits = fUse8BitDepth ? (LPBYTE)g_DisconImage8Bits :
(LPBYTE)g_DisconImageBits;
ULONG cbBitmapLen = fUse8BitDepth ? g_cbDisconImage8Bits :
g_cbDisconImageBits;
_hbmDisconImg = (HBITMAP)LoadImageFromMemory(
hdcScreen,
(LPBYTE)pBitmapBits,
cbBitmapLen
);
if ((_hbmDisconImg != NULL) &&
(GetObject(_hbmDisconImg,
sizeof(bitmap), &bitmap) >= sizeof(bitmap))) {
SetRect(&_rcDisconImg, 0, 0, bitmap.bmWidth, bitmap.bmHeight);
_hPalette = CUT::UT_GetPaletteForBitmap(NULL, _hbmDisconImg);
}
ReleaseDC(NULL, hdcScreen);
hdcScreen = NULL;
}
#endif
_fInitialized = (_hbmDisconImg && _pUi);
if (!_fInitialized) {
TRC_ERR((TB,_T("Failed to properly init arc dlg")));
}
DC_END_FN();
}
CAutoReconnectPlainUI::~CAutoReconnectPlainUI()
{
#ifndef OS_WINCE
if (_hbmDisconImg) {
DeleteObject(_hbmDisconImg);
_hbmDisconImg = NULL;
}
#endif
if (_hPalette) {
DeleteObject(_hPalette);
_hPalette = NULL;
}
}
#define ARC_PLAIN_WNDCLASS _T("ARCICON")
HWND CAutoReconnectPlainUI::StartModeless()
{
LONG_PTR dwStyle;
WNDCLASS tmpWndClass;
WNDCLASS plainArcWndClass;
ATOM registerClassRc;
DC_BEGIN_FN("StartModeless");
if (!_fInitialized) {
TRC_ERR((TB,_T("failing startmodeless fInitialized is FALSE")));
return NULL;
}
//
// Create a window to host the UI
//
//
// Register the class for the Main Window
//
if (!GetClassInfo(_hInstance, ARC_PLAIN_WNDCLASS, &tmpWndClass))
{
TRC_NRM((TB, _T("Register Main Window class")));
plainArcWndClass.style = CS_DBLCLKS;
plainArcWndClass.lpfnWndProc = StaticPlainArcWndProc;
plainArcWndClass.cbClsExtra = 0;
plainArcWndClass.cbWndExtra = sizeof(void*); //store 'this' pointer
plainArcWndClass.hInstance = _hInstance;
plainArcWndClass.hIcon = NULL;
plainArcWndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
plainArcWndClass.hbrBackground = (HBRUSH) GetStockObject(HOLLOW_BRUSH);
plainArcWndClass.lpszMenuName = NULL;
plainArcWndClass.lpszClassName = ARC_PLAIN_WNDCLASS;
registerClassRc = RegisterClass (&plainArcWndClass);
if (registerClassRc == 0)
{
TRC_ERR((TB,_T("RegisterClass failed: 0x%x"), GetLastError()));
DC_QUIT;
}
}
_hwnd = CreateWindow(ARC_PLAIN_WNDCLASS,
NULL,
WS_CHILD | WS_CLIPSIBLINGS,
0,
0,
_rcDisconImg.right - _rcDisconImg.left,
_rcDisconImg.bottom - _rcDisconImg.top,
_hwndOwner,
NULL,
_hInstance,
this
);
if (_hwnd) {
//
// Move window to the parent's top-right and then show the window
//
MoveToParentTopRight();
ShowTopMost();
_fIsUiVisible = TRUE;
}
else {
TRC_ERR((TB,_T("CreateWindow failed: 0x%x"), GetLastError()));
}
DC_EXIT_POINT:
DC_END_FN();
return _hwnd;
}
BOOL CAutoReconnectPlainUI::ShowTopMost()
{
BOOL rc = FALSE;
DC_BEGIN_FN("ShowTopMost");
if (!_hwnd) {
DC_QUIT;
}
ShowWindow(_hwnd, SW_SHOWNORMAL);
//
// Bring the window to the TOP of the Z order
//
SetWindowPos( _hwnd,
HWND_TOPMOST,
0, 0, 0, 0,
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE );
rc = TRUE;
DC_EXIT_POINT:
DC_END_FN();
return rc;
}
//
// Position offset from the edge
//
#define ICON_POSITION_OFFSET 20
VOID
CAutoReconnectPlainUI::MoveToParentTopRight()
{
RECT rcParent;
INT xPos, yPos;
DC_BEGIN_FN("OnParentSizePosChange");
//
// Reposition the dialog to the top right
// of the owner window
//
if (_hwnd && _hwndOwner) {
//
// Position the window in the top-right of the parent
//
GetClientRect(_hwndOwner, &rcParent);
xPos = rcParent.right - ICON_POSITION_OFFSET -
(_rcDisconImg.right - _rcDisconImg.left);
yPos = rcParent.top + ICON_POSITION_OFFSET;
SetWindowPos(_hwnd,
NULL,
xPos, yPos,
0, 0,
SWP_NOSIZE | SWP_NOACTIVATE);
}
DC_END_FN();
}
VOID
CAutoReconnectPlainUI::OnParentSizePosChange()
{
MoveToParentTopRight();
}
//
// Handler for WM_ERASEBKGND (See platform sdk docs)
//
VOID
CAutoReconnectPlainUI::OnEraseBkgnd(
HWND hwnd,
HDC hdc
)
{
RECT rc;
HPALETTE hPaletteOld = NULL;
DC_BEGIN_FN("OnEraseBkgnd");
TRC_ASSERT(_hbmDisconImg, (TB,_T("_hbmBackground is NULL")));
if (GetClientRect(hwnd, &rc)) {
hPaletteOld = SelectPalette(hdc, _hPalette, FALSE);
RealizePalette(hdc);
PaintBitmap(hdc, &rc, _hbmDisconImg, &_rcDisconImg);
SelectPalette(hdc, hPaletteOld, FALSE);
RealizePalette(hdc);
}
DC_END_FN();
}
//
// Handler for WM_PRINTCLIENT
//
VOID
CAutoReconnectPlainUI::OnPrintClient(
HWND hwnd,
HDC hdcPrint,
DWORD dwOptions)
{
DC_BEGIN_FN("OnPrintClient");
#ifndef OS_WINCE
if ((dwOptions & (PRF_ERASEBKGND | PRF_CLIENT)) != 0)
{
OnEraseBkgnd(hwnd, hdcPrint);
}
#endif
DC_END_FN();
}
//
// StaticPlainArcWndProc
// Params: see platform sdk for wndproc
//
// Delegates work to appropriate instance
//
//
LRESULT CALLBACK
CAutoReconnectPlainUI::StaticPlainArcWndProc(
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
INT retVal = 0;
CAutoReconnectPlainUI* pUI;
DC_BEGIN_FN("StaticPlainArcWndProc");
pUI = (CAutoReconnectPlainUI*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
if(WM_CREATE == uMsg)
{
//pull out the this pointer and stuff it in the window class
LPCREATESTRUCT lpcs = (LPCREATESTRUCT) lParam;
pUI = (CAutoReconnectPlainUI*)lpcs->lpCreateParams;
SetWindowLongPtr( hwnd, GWLP_USERDATA, (LONG_PTR)pUI);
}
//
// Delegate the message to the appropriate instance
//
if(pUI) {
return pUI->WndProc(hwnd, uMsg, wParam, lParam);
}
else {
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
DC_EXIT_POINT:
DC_END_FN();
return retVal;
}
#define ARC_PLAIN_UI_TIMERID 1
#define ARC_ANIM_TIME 400
//
// Name: WndProc
//
// Purpose: Handles AutoReconnect dialog box proc
//
// Returns: TRUE if message dealt with
// FALSE otherwise
//
// Params: See windows documentation
//
//
LRESULT CALLBACK CAutoReconnectPlainUI::WndProc(HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
INT_PTR rc = FALSE;
DC_BEGIN_FN("DialogBoxProc");
switch (uMsg)
{
case WM_CREATE:
{
_nFlashingTimer = SetTimer(hwnd, ARC_PLAIN_UI_TIMERID,
ARC_ANIM_TIME,
NULL
);
if (_nFlashingTimer) {
SetFocus(hwnd);
}
else {
TRC_ERR((TB,_T("SetTimer failed - 0x%x"),
GetLastError()));
rc = -1;
}
}
break;
case WM_DESTROY:
{
if (_nFlashingTimer) {
KillTimer(hwnd, _nFlashingTimer);
_nFlashingTimer = 0;
}
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)NULL);
}
break;
case WM_TIMER:
{
//
// DO animation stuff
//
OnAnimFlashTimer();
}
break;
case WM_ERASEBKGND:
{
OnEraseBkgnd(hwnd, (HDC)wParam);
rc = 1;
}
break;
case WM_KEYUP:
{
if (VK_ESCAPE == wParam) {
TRC_NRM((TB,_T("ARC ESC pressed, disconnect")));
_pUi->UI_UserInitiatedDisconnect(_lastDiscReason);
_fContinueReconAttempts = FALSE;
}
}
break;
case WM_SETFOCUS:
{
TRC_NRM((TB,_T("Setfocus to arc")));
}
break;
case WM_KILLFOCUS:
{
TRC_NRM((TB,_T("killfocus to arc: 0x%x 0x%x"), wParam, lParam));
}
break;
#ifndef OS_WINCE
case WM_PRINTCLIENT:
{
OnPrintClient(hwnd, (HDC)wParam, (DWORD)lParam);
rc = 1;
}
break;
#endif
default:
{
return DefWindowProc( hwnd, uMsg, wParam, lParam);
}
break;
}
DC_END_FN();
return(rc);
} /* DialogBoxProc */
VOID
CAutoReconnectPlainUI::OnAnimFlashTimer()
{
//
// Toggle UI hide state
//
_fIsUiVisible = !_fIsUiVisible;
ShowWindow(_hwnd, _fIsUiVisible ? SW_SHOWNORMAL : SW_HIDE);
}
//
// Called to notify us that we got disconnected
// this means the last connection attempt failed
//
// Params:
// discReason - disconnect major reason code
// attemptCount - attempt count so far
// pfContinueArc - [OUT] set to FALSE to stop ARC
//
VOID
CAutoReconnectPlainUI::OnNotifyAutoReconnecting(
UINT discReason,
ULONG attemptCount,
ULONG maxAttemptCount,
BOOL* pfContinueArc
)
{
DC_BEGIN_FN("OnNotifyDisconnected");
_lastDiscReason = discReason;
if (!_fContinueReconAttempts) {
TRC_NRM((TB,_T("Stopping arc - _fContinueReconAttempts is FALSE")));
}
*pfContinueArc = _fContinueReconAttempts;
DC_END_FN();
}
//
// Called to notify us that we have connected
//
VOID CAutoReconnectPlainUI::OnNotifyConnected()
{
DC_BEGIN_FN("OnNotifyConnected");
_fContinueReconAttempts = FALSE;
DC_END_FN();
}
//
// Destory
// Called to kill and cleanup the dialog
//
//
BOOL
CAutoReconnectPlainUI::Destroy()
{
DC_BEGIN_FN("Destroy");
if (!DestroyWindow(_hwnd)) {
TRC_ERR((TB,_T("DestroyWindow failed: 0x%x"),
GetLastError()));
}
DC_END_FN();
return TRUE;
}
//
// Load a bitmap from memory
//
// Params:
// pbBitmapBits - pointer to bitmap bits (e.g. can pass in file mapping
// to a BMP file).
//
// cbLen - length of pbBitmapBits
//
// Returns:
// HBITMAP - handle to the bitmap
//
HBITMAP
CAutoReconnectPlainUI::LoadImageFromMemory(
HDC hdc,
LPBYTE pbBitmapBits,
ULONG cbLen
)
{
HRESULT hr;
HBITMAP hbmp = NULL;
LPBITMAPINFO pbmi = NULL;
ULONG cbBmiLen = 0;
PBYTE pBitmapBits = NULL;
ULONG cbBitmapBits = 0;
hr = LoadImageBits(
pbBitmapBits,
cbLen,
&pbmi,
&cbBmiLen,
&pBitmapBits,
&cbBitmapBits
);
if (SUCCEEDED(hr)) {
hbmp = CreateDIBitmap(hdc,
&pbmi->bmiHeader,
CBM_INIT,
pBitmapBits,
pbmi,
DIB_RGB_COLORS
);
delete pBitmapBits;
delete pbmi;
}
return hbmp;
}
#define BMP_24_BITSPERPIXEL 24
#define BMP_16_BITSPERPIXEL 16
#define BMP_32_BITSPERPIXEL 32
//
// Worker function for image load, caller frees outparam bits
//
HRESULT
CAutoReconnectPlainUI::LoadImageBits(
LPBYTE pbBitmapBits, ULONG cbLen,
LPBITMAPINFO* ppBitmapInfo, PULONG pcbBitmapInfo,
LPBYTE* ppBits, PULONG pcbBits
)
{
HRESULT hr = ResultFromScode(S_OK);
BITMAPFILEHEADER bmfh;
BITMAPCOREHEADER *pbch;
BITMAPINFOHEADER bih;
LPBYTE pbStart;
ULONG cbi = 0;
ULONG cbData;
LPBITMAPINFO pbi = NULL;
LPBYTE pbData = NULL;
DWORD dwSizeOfHeader;
//
// Record the starting position
//
pbStart = pbBitmapBits;
//
// First validate the buffer for size
//
if (cbLen < sizeof(BITMAPFILEHEADER))
{
return(ResultFromScode(E_FAIL));
}
//
// Now get the bitmap file header
//
memcpy(&bmfh, pbBitmapBits, sizeof(BITMAPFILEHEADER));
//
// Validate the header
//
if (!(bmfh.bfType == 0x4d42) && (bmfh.bfOffBits <= cbLen))
{
return E_FAIL;
}
//
// Get the next 4 bytes which will represent the size of the
// next structure and allow us to determine the type
//
if (SUCCEEDED(hr))
{
pbBitmapBits += sizeof(BITMAPFILEHEADER);
memcpy(&dwSizeOfHeader, pbBitmapBits, sizeof(DWORD));
if (dwSizeOfHeader == sizeof(BITMAPCOREHEADER))
{
pbch = (BITMAPCOREHEADER *)pbBitmapBits;
memset(&bih, 0, sizeof(BITMAPINFOHEADER));
bih.biSize = sizeof(BITMAPINFOHEADER);
bih.biWidth = pbch->bcWidth;
bih.biHeight = pbch->bcHeight;
bih.biPlanes = pbch->bcPlanes;
bih.biBitCount = pbch->bcBitCount;
pbBitmapBits += sizeof(BITMAPCOREHEADER);
}
else if (dwSizeOfHeader == sizeof(BITMAPINFOHEADER))
{
memcpy(&bih, pbBitmapBits, sizeof(BITMAPINFOHEADER));
pbBitmapBits += sizeof(BITMAPINFOHEADER);
}
else
{
hr = ResultFromScode(E_FAIL);
}
}
//
// Check if biClrUsed is set since we do not handle that
// case at this time
//
if (SUCCEEDED(hr))
{
if (bih.biClrUsed != 0)
{
hr = ResultFromScode(E_FAIL);
}
}
//
// Now we need to calculate the size of the BITMAPINFO we need
// to allocate including any palette information
//
if (SUCCEEDED(hr))
{
//
// First the size of the header
//
cbi = sizeof(BITMAPINFOHEADER);
//
// Now the palette
//
if (bih.biBitCount == BMP_24_BITSPERPIXEL)
{
//
// Just add on the 1 RGBQUAD for the structure but
// there is no palette
//
cbi += sizeof(RGBQUAD);
}
else if ((bih.biBitCount == BMP_16_BITSPERPIXEL) ||
(bih.biBitCount == BMP_32_BITSPERPIXEL))
{
//
// Add on the 3 DWORD masks which are used to
// get the colors out of the data
//
cbi += (3 * sizeof(DWORD));
}
else
{
//
// Anything else we just use the bit count to calculate
// the number of entries
//
cbi += ((1 << bih.biBitCount) * sizeof(RGBQUAD));
}
//
// Now allocate the BITMAPINFO
//
pbi = (LPBITMAPINFO) new BYTE [cbi];
if (pbi == NULL)
{
hr = ResultFromScode(E_OUTOFMEMORY);
}
}
//
// Fill in the BITMAPINFO data structure and get the bits
//
if (SUCCEEDED(hr))
{
//
// First copy the header data
//
memcpy(&(pbi->bmiHeader), &bih, sizeof(BITMAPINFOHEADER));
//
// Now the palette data
//
if (bih.biBitCount == BMP_24_BITSPERPIXEL)
{
//
// No palette data to copy
//
}
else if ((bih.biBitCount == BMP_16_BITSPERPIXEL) ||
(bih.biBitCount == BMP_32_BITSPERPIXEL))
{
//
// Copy the 3 DWORD masks
//
memcpy(&(pbi->bmiColors), pbBitmapBits, 3*sizeof(DWORD));
}
else
{
//
// If we were a BITMAPCOREHEADER type then we have our
// palette data in the form of RGBTRIPLEs so we must
// explicitly copy each. Otherwise we can just memcpy
// the RGBQUADs
//
if (dwSizeOfHeader == sizeof(BITMAPCOREHEADER))
{
ULONG cPalEntry = (1 << bih.biBitCount);
ULONG cCount;
RGBTRIPLE *argbt = (RGBTRIPLE *)pbBitmapBits;
for (cCount = 0; cCount < cPalEntry; cCount++)
{
pbi->bmiColors[cCount].rgbRed =
argbt[cCount].rgbtRed;
pbi->bmiColors[cCount].rgbGreen =
argbt[cCount].rgbtGreen;
pbi->bmiColors[cCount].rgbBlue =
argbt[cCount].rgbtBlue;
pbi->bmiColors[cCount].rgbReserved = 0;
}
}
else
{
ULONG cbPalette = (1 << bih.biBitCount) * sizeof(RGBQUAD);
memcpy(&(pbi->bmiColors), pbBitmapBits, cbPalette);
}
}
//
// Now find out where the bits are
//
pbBitmapBits = pbStart + bmfh.bfOffBits;
//
// Get the size to copy
//
cbData = cbLen - bmfh.bfOffBits;
//
// Allocate the buffer to hold the bits
//
pbData = new BYTE [cbData];
if (pbData == NULL)
{
hr = ResultFromScode(E_OUTOFMEMORY);
}
if (SUCCEEDED(hr))
{
memcpy(pbData, pbBitmapBits, cbData);
}
}
//
// If everything succeeded record the data
//
if (SUCCEEDED(hr))
{
//
// Record the info
//
*pcbBitmapInfo = cbi;
*ppBitmapInfo = pbi;
//
// Record the data
//
*ppBits = pbData;
*pcbBits = cbData;
}
else
{
//
// Cleanup
//
delete pbi;
delete pbData;
}
return(hr);
}
#endif // ARC_MINIMAL_UI