|
|
/*******************************************************************************
* * (C) COPYRIGHT MICROSOFT CORPORATION, 1998 * * TITLE: MISCUTIL.CPP * * VERSION: 1.0 * * AUTHOR: ShaunIv * * DATE: 5/28/1998 * * DESCRIPTION: Various utility functions we use in more than one place * *******************************************************************************/
#include "precomp.h"
#pragma hdrstop
#include <advpub.h> // For RegInstall and related data structures
#include <windowsx.h> // For RegInstall and related data structures
#include "wiaffmt.h"
#include "shellext.h"
namespace WiaUiUtil {
LONG Align( LONG n , LONG m ) { return(n % m) ? (((n/m)+1)*m) : (n); }
/*
* StringToLong: Convert a string to a long. ASCII Arabic numerals only */ LONG StringToLong( LPCTSTR pszStr ) { LPTSTR pstr = (LPTSTR)pszStr; bool bNeg = (*pstr == TEXT('-')); if (bNeg) pstr++; LONG nTotal = 0; while (*pstr && *pstr >= TEXT('0') && *pstr <= TEXT('9')) { nTotal *= 10; nTotal += *pstr - TEXT('0'); ++pstr; } return(bNeg ? -nTotal : nTotal); }
SIZE MapDialogSize( HWND hwnd, const SIZE &size ) { RECT rcTmp; rcTmp.left = rcTmp.top = 0; rcTmp.right = size.cx; rcTmp.bottom = size.cy; MapDialogRect( hwnd, &rcTmp ); SIZE sizeTmp; sizeTmp.cx = rcTmp.right; sizeTmp.cy = rcTmp.bottom; return (sizeTmp); }
/*******************************************************************************
* * GetBmiSize * * DESCRIPTION: * Should never get biCompression == BI_RLE. * * PARAMETERS: * *******************************************************************************/ LONG GetBmiSize(PBITMAPINFO pbmi) { WIA_PUSH_FUNCTION((TEXT("WiaUiUtil::GetBmiSize(0x%p)"), pbmi )); // determine the size of bitmapinfo
LONG lSize = pbmi->bmiHeader.biSize;
// no color table cases
if ( (pbmi->bmiHeader.biBitCount == 24) || ((pbmi->bmiHeader.biBitCount == 32) && (pbmi->bmiHeader.biCompression == BI_RGB))) {
// no colors unless stated
lSize += sizeof(RGBQUAD) * pbmi->bmiHeader.biClrUsed; return(lSize); }
// bitfields cases
if (((pbmi->bmiHeader.biBitCount == 32) && (pbmi->bmiHeader.biCompression == BI_BITFIELDS)) || (pbmi->bmiHeader.biBitCount == 16)) {
lSize += 3 * sizeof(RGBQUAD); return(lSize); }
// palette cases
if (pbmi->bmiHeader.biBitCount == 1) {
LONG lPal = pbmi->bmiHeader.biClrUsed;
if ((lPal == 0) || (lPal > 2)) { lPal = 2; }
lSize += lPal * sizeof(RGBQUAD); return(lSize); }
// palette cases
if (pbmi->bmiHeader.biBitCount == 4) {
LONG lPal = pbmi->bmiHeader.biClrUsed;
if ((lPal == 0) || (lPal > 16)) { lPal = 16; }
lSize += lPal * sizeof(RGBQUAD); return(lSize); }
// palette cases
if (pbmi->bmiHeader.biBitCount == 8) {
LONG lPal = pbmi->bmiHeader.biClrUsed;
if ((lPal == 0) || (lPal > 256)) { lPal = 256; }
lSize += lPal * sizeof(RGBQUAD); return(lSize); }
// error
return(0); }
// Simple wrapper for MsgWaitForMultipleObjects
bool MsgWaitForSingleObject( HANDLE hHandle, DWORD dwMilliseconds ) { bool bEventOccurred = false; const int nCount = 1; while (true) { DWORD dwRes = MsgWaitForMultipleObjects(nCount,&hHandle,FALSE,dwMilliseconds,QS_ALLINPUT|QS_ALLPOSTMESSAGE); if (WAIT_OBJECT_0==dwRes) { // The handle was signalled, so we can break out of our loop, returning true
bEventOccurred = true; break; } else if (WAIT_OBJECT_0+nCount==dwRes) { // pull all of the messages out of the queue and process them
MSG msg; while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) { if (msg.message == WM_QUIT) break; TranslateMessage(&msg); DispatchMessage(&msg); } } else { // The handle either timed out, or the mutex was abandoned, so we can break out of our loop, returning false
break; } } return bEventOccurred; }
void CenterWindow( HWND hWnd, HWND hWndParent ) { if (IsWindow(hWnd)) {
if (!hWndParent) { //
// If the window to be centered on is NULL, use the desktop window
//
hWndParent = GetDesktopWindow(); } else { //
// If the window to be centered on is minimized, use the desktop window
//
DWORD dwStyle = GetWindowLong(hWndParent, GWL_STYLE); if (dwStyle & WS_MINIMIZE) { hWndParent = GetDesktopWindow(); } }
//
// Get the window rects
//
RECT rcParent, rcCurrent; GetWindowRect( hWndParent, &rcParent ); GetWindowRect( hWnd, &rcCurrent );
//
// Get the desired coordinates for the upper-left hand corner
//
RECT rcFinal; rcFinal.left = rcParent.left + (RectWidth(rcParent) - RectWidth(rcCurrent))/2; rcFinal.top = rcParent.top + (RectHeight(rcParent) - RectHeight(rcCurrent))/2; rcFinal.right = rcFinal.left + RectWidth(rcCurrent); rcFinal.bottom = rcFinal.top + RectHeight(rcCurrent);
//
// Make sure we're not off the screen
//
HMONITOR hMonitor = MonitorFromRect( &rcFinal, MONITOR_DEFAULTTONEAREST ); if (hMonitor) { MONITORINFO MonitorInfo; ZeroMemory( &MonitorInfo, sizeof(MonitorInfo) ); MonitorInfo.cbSize = sizeof(MonitorInfo); //
// Get the screen coordinates of this monitor
//
if (GetMonitorInfo(hMonitor, &MonitorInfo)) { //
// Ensure the window is in the working area's region
//
rcFinal.left = Max<int>(MonitorInfo.rcWork.left, Min<int>( MonitorInfo.rcWork.right - RectWidth(rcCurrent), rcFinal.left )); rcFinal.top = Max<int>(MonitorInfo.rcWork.top, Min<int>( MonitorInfo.rcWork.bottom - RectHeight(rcCurrent), rcFinal.top )); } }
// Move it
SetWindowPos( hWnd, NULL, rcFinal.left, rcFinal.top, 0, 0, SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOZORDER ); } }
// Flip an image horizontally
bool FlipImage( PBYTE pBits, LONG nWidth, LONG nHeight, LONG nBitDepth ) { bool bResult = false; if (pBits && nWidth>=0 && nHeight>=0 && nBitDepth>=0) { LONG nLineWidthInBytes = WiaUiUtil::Align(nWidth*nBitDepth,sizeof(DWORD)*8)/8; PBYTE pTempLine = new BYTE[nLineWidthInBytes]; if (pTempLine) { for (int i=0;i<nHeight/2;i++) { PBYTE pSrc = pBits + (i * nLineWidthInBytes); PBYTE pDst = pBits + ((nHeight-i-1) * nLineWidthInBytes); CopyMemory( pTempLine, pSrc, nLineWidthInBytes ); CopyMemory( pSrc, pDst, nLineWidthInBytes ); CopyMemory( pDst, pTempLine, nLineWidthInBytes ); } bResult = true; } delete[] pTempLine; } return bResult; }
HRESULT InstallInfFromResource( HINSTANCE hInstance, LPCSTR pszSectionName ) { HRESULT hr; HINSTANCE hInstAdvPackDll = LoadLibrary(TEXT("ADVPACK.DLL")); if (hInstAdvPackDll) { REGINSTALL pfnRegInstall = reinterpret_cast<REGINSTALL>(GetProcAddress( hInstAdvPackDll, "RegInstall" )); if (pfnRegInstall) { #if defined(WINNT)
STRENTRY astrEntry[] = { { "25", "%SystemRoot%" }, { "11", "%SystemRoot%\\system32" } }; STRTABLE strTable = { sizeof(astrEntry)/sizeof(astrEntry[0]), astrEntry }; hr = pfnRegInstall(hInstance, pszSectionName, &strTable); #else
hr = pfnRegInstall(hInstance, pszSectionName, NULL); #endif
} else hr = HRESULT_FROM_WIN32(GetLastError()); FreeLibrary(hInstAdvPackDll); } else hr = HRESULT_FROM_WIN32(GetLastError()); return hr; }
/******************************************************************************
WriteDIBToFile
Writes a DIB to a file.
******************************************************************************/ HRESULT WriteDIBToFile( HBITMAP hDib, HANDLE hFile ) { if (!hDib) { return E_INVALIDARG; }
// Make sure this is a valid DIB and get this useful info.
DIBSECTION ds; if (!GetObject( hDib, sizeof(DIBSECTION), &ds )) { return E_INVALIDARG; }
// We only deal with DIBs
if (ds.dsBm.bmPlanes != 1) { return E_INVALIDARG; }
// Calculate some color table sizes
int nColors = ds.dsBmih.biBitCount <= 8 ? 1 << ds.dsBmih.biBitCount : 0; int nBitfields = ds.dsBmih.biCompression == BI_BITFIELDS ? 3 : 0;
// Calculate the data size
int nImageDataSize = ds.dsBmih.biSizeImage ? ds.dsBmih.biSizeImage : ds.dsBm.bmWidthBytes * ds.dsBm.bmHeight;
// Get the color table (if needed)
RGBQUAD rgbqaColorTable[256] = {0}; if (nColors) { HDC hDC = CreateCompatibleDC(NULL); if (hDC) { HBITMAP hOldBitmap = reinterpret_cast<HBITMAP>(SelectObject(hDC,hDib)); GetDIBColorTable( hDC, 0, nColors, rgbqaColorTable ); SelectObject(hDC,hOldBitmap); DeleteDC( hDC ); } }
// Create the file header
BITMAPFILEHEADER bmfh; bmfh.bfType = 'MB'; bmfh.bfSize = 0; bmfh.bfReserved1 = 0; bmfh.bfReserved2 = 0; bmfh.bfOffBits = sizeof(bmfh) + sizeof(ds.dsBmih) + nBitfields*sizeof(DWORD) + nColors*sizeof(RGBQUAD);
// Start writing! Note that we write out the bitfields and the color table. Only one,
// at most, will actually result in data being written
DWORD dwBytesWritten; if (!WriteFile( hFile, &bmfh, sizeof(bmfh), &dwBytesWritten, NULL )) return HRESULT_FROM_WIN32(GetLastError()); if (!WriteFile( hFile, &ds.dsBmih, sizeof(ds.dsBmih), &dwBytesWritten, NULL )) return HRESULT_FROM_WIN32(GetLastError()); if (!WriteFile( hFile, &ds.dsBitfields, nBitfields*sizeof(DWORD), &dwBytesWritten, NULL )) return HRESULT_FROM_WIN32(GetLastError()); if (!WriteFile( hFile, rgbqaColorTable, nColors*sizeof(RGBQUAD), &dwBytesWritten, NULL )) return HRESULT_FROM_WIN32(GetLastError()); if (!WriteFile( hFile, ds.dsBm.bmBits, nImageDataSize, &dwBytesWritten, NULL )) return HRESULT_FROM_WIN32(GetLastError()); return S_OK; }
HFONT ChangeFontFromWindow( HWND hWnd, int nPointSizeDelta ) { HFONT hFontResult = NULL;
//
// Get the window's font
//
HFONT hFont = GetFontFromWindow(hWnd); if (hFont) { LOGFONT LogFont = {0}; if (GetObject( hFont, sizeof(LogFont), &LogFont )) { HDC hDC = GetDC(hWnd); if (hDC) { HFONT hOldFont = SelectFont(hDC,hFont); TEXTMETRIC TextMetric = {0}; if (GetTextMetrics( hDC, &TextMetric )) { //
// Get the current font's point size
//
int nPointSize = MulDiv( TextMetric.tmHeight-TextMetric.tmInternalLeading, 72, GetDeviceCaps(hDC, LOGPIXELSY) ) + nPointSizeDelta;
//
// Calculate the height of the new font
//
LogFont.lfHeight = -MulDiv(nPointSize, GetDeviceCaps(hDC, LOGPIXELSY), 72);
//
// Create the font
//
hFontResult = CreateFontIndirect( &LogFont ); }
if (hOldFont) { SelectFont( hDC, hOldFont ); }
ReleaseDC( hWnd, hDC ); } } } return hFontResult; }
HFONT GetFontFromWindow( HWND hWnd ) { //
// Get the window's font
//
HFONT hFontResult = reinterpret_cast<HFONT>(SendMessage(hWnd,WM_GETFONT,0,0)); if (!hFontResult) { hFontResult = reinterpret_cast<HFONT>(GetStockObject(DEFAULT_GUI_FONT)); } return hFontResult; }
HFONT CreateFontWithPointSizeFromWindow( HWND hWnd, int nPointSize, bool bBold, bool bItalic ) { HFONT hFontResult = NULL; HFONT hFont = GetFontFromWindow(hWnd); if (hFont) { LOGFONT LogFont = {0}; if (GetObject( hFont, sizeof(LogFont), &LogFont )) { HDC hDC = GetDC(NULL); if (hDC) { if (nPointSize) { LogFont.lfHeight = -MulDiv(nPointSize, GetDeviceCaps(hDC, LOGPIXELSY), 72); } if (bBold) { LogFont.lfWeight = FW_BOLD; } if (bItalic) { LogFont.lfItalic = TRUE; } hFontResult = CreateFontIndirect( &LogFont ); ReleaseDC( NULL, hDC ); } } } return hFontResult; }
/*******************************************************************************
* FindLowestNumberedFile * * Returns lowest numbered file that can contain the requested series of file * name, or zero if it can't find such a range. * * pszFileAndPathnameMask should be a printf-style format string containing the * full path name to a file: * * Example: "C:\foo\bar\filename %03d.ext" * * It would check for the existence of: * * "C:\foo\bar\filename 001.ext", "C:\foo\bar\filename 002.ext", etc... * * until it found a block large enough to hold nCount files. * *******************************************************************************/ int FindLowestNumberedFile( LPCTSTR pszFileAndPathnameMask, int nCount, int nMax ) { // Start at one (users never start counting at 0)
int i=1; while (i<=nMax-nCount+1) { // Assume we'll be able to store the sequence
bool bEnoughRoom = true; for (int j=0;j<nCount && bEnoughRoom;j++) { // Add a few bytes to the max len, just in case
TCHAR szFile[MAX_PATH + 10];
// Create the potential filename
wsprintf( szFile, pszFileAndPathnameMask, i + j );
// Look for this file
WIN32_FIND_DATA FindFileData; ZeroMemory( &FindFileData, sizeof(FindFileData)); HANDLE hFindFiles = FindFirstFile( szFile, &FindFileData ); if (hFindFiles != INVALID_HANDLE_VALUE) { FindClose(hFindFiles);
// Didn't make it
bEnoughRoom = false;
// Skip this series. No need to start at the bottom.
i += j; } } // If we made it through, return the base number, otherwise increment by one
if (bEnoughRoom) return i; else i++; } // We never found room...
return -1; }
/*******************************************************************************
* FindLowestNumberedFile * * Returns lowest numbered file that can contain the requested series of file * name, or zero if it can't find such a range. * * pszFileAndPathnameMask should be a printf-style format string containing the * full path name to a file: * * Example: "C:\foo\bar\filename %03d.ext" * * It would check for the existence of: * * "C:\foo\bar\filename 001.ext", "C:\foo\bar\filename 002.ext", etc... * * until it found a block large enough to hold nCount files. * *******************************************************************************/ int FindLowestNumberedFile( LPCTSTR pszFileAndPathnameMaskPrefix, LPCTSTR pszFormatString, LPCTSTR pszFileAndPathnameMaskSuffix, int nCount, int nMax ) { TCHAR szFilename[MAX_PATH]; if (nCount == 1) { lstrcpyn( szFilename, pszFileAndPathnameMaskPrefix, ARRAYSIZE(szFilename) ); lstrcpyn( szFilename+lstrlen(szFilename), pszFileAndPathnameMaskSuffix, ARRAYSIZE(szFilename)-lstrlen(szFilename) ); if (GetFileAttributes(szFilename) == 0xFFFFFFFF) return 0; }
// Use the normal method of calculating the lowest numbered file
lstrcpyn( szFilename, pszFileAndPathnameMaskPrefix, ARRAYSIZE(szFilename) ); lstrcpyn( szFilename+lstrlen(szFilename), pszFormatString, ARRAYSIZE(szFilename)-lstrlen(szFilename) ); lstrcpyn( szFilename+lstrlen(szFilename), pszFileAndPathnameMaskSuffix, ARRAYSIZE(szFilename)-lstrlen(szFilename) ); return FindLowestNumberedFile( szFilename, nCount, nMax ); }
SIZE GetTextExtentFromWindow( HWND hFontWnd, LPCTSTR pszString ) { SIZE sizeResult = {0,0}; HDC hDC = GetDC( hFontWnd ); if (hDC) { HFONT hFont = GetFontFromWindow(hFontWnd); if (hFont) { HFONT hOldFont = SelectFont( hDC, hFont );
SIZE sizeExtent = {0,0}; if (GetTextExtentPoint32( hDC, pszString, lstrlen(pszString), &sizeExtent )) { sizeResult = sizeExtent; } //
// Restore the DC
//
if (hOldFont) { SelectFont( hDC, hOldFont ); } } ReleaseDC( hFontWnd, hDC ); } return sizeResult; }
CSimpleString TruncateTextToFitInRect( HWND hFontWnd, LPCTSTR pszString, RECT rectTarget, UINT nDrawTextFormat ) { WIA_PUSH_FUNCTION((TEXT("WiaUiUtil::TruncateTextToFitInRect( 0x%p, %s, (%d,%d,%d,%d), 0x%08X"), hFontWnd, pszString, rectTarget.left, rectTarget.top, rectTarget.right, rectTarget.bottom, nDrawTextFormat )); CSimpleString strResult = pszString;
//
// Make sure we have valid parameters
//
if (IsWindow(hFontWnd) && hFontWnd && pszString && lstrlen(pszString)) { //
// Make a copy of the string. If it fails, we will just return the original string.
//
LPTSTR pszTemp = new TCHAR[lstrlen(pszString)+1]; if (pszTemp) { lstrcpy( pszTemp, pszString );
//
// Get a client DC for the window
//
HDC hDC = GetDC( hFontWnd ); if (hDC) { //
// Create a memory DC
//
HDC hMemDC = CreateCompatibleDC( hDC ); if (hMemDC) { //
// Get the font the window is using and select it into our client dc
//
HFONT hFont = GetFontFromWindow(hFontWnd); if (hFont) { //
// Select the font
//
HFONT hOldFont = SelectFont( hMemDC, hFont );
//
// Modify the string using DrawText
//
if (DrawText( hMemDC, pszTemp, lstrlen(pszTemp), &rectTarget, nDrawTextFormat|DT_MODIFYSTRING|DT_SINGLELINE )) { strResult = pszTemp; } else { WIA_ERROR((TEXT("DrawText failed"))); } //
// Restore the DC
//
if (hOldFont) { SelectFont( hMemDC, hOldFont ); }
}
//
// Clean up the memory DC
//
DeleteDC( hMemDC ); } else { WIA_ERROR((TEXT("Unable to create the compatible DC"))); }
//
// Release the DC
//
ReleaseDC( hFontWnd, hDC ); } else { WIA_ERROR((TEXT("Unable to get the DC"))); }
//
// Clean up our temp buffer
//
delete[] pszTemp; } else { WIA_ERROR((TEXT("Unable to allocate the temp buffer"))); } } else { WIA_ERROR((TEXT("Argument validation failed"))); } return strResult; }
CSimpleString FitTextInStaticWithEllipsis( LPCTSTR pszString, HWND hWndStatic, UINT nDrawTextStyle ) { //
// Make sure we have valid parameters
//
if (!hWndStatic || !pszString || !IsWindow(hWndStatic)) { return pszString; }
//
// Hide prefix characters?
//
if (GetWindowLong( hWndStatic, GWL_STYLE ) & SS_NOPREFIX) { nDrawTextStyle |= DT_NOPREFIX; }
//
// How big is the area we are trying to fit this in?
//
RECT rcClient; GetClientRect( hWndStatic, &rcClient );
//
// Calculate the result and return it
//
return TruncateTextToFitInRect( hWndStatic, pszString, rcClient, nDrawTextStyle ); }
//
// Get the size of an icon
//
bool GetIconSize( HICON hIcon, SIZE &sizeIcon ) { //
// Assume failure
//
bool bSuccess = false;
//
// Get the icon information
//
ICONINFO IconInfo = {0}; if (GetIconInfo( hIcon, &IconInfo )) { //
// Get one of the bitmaps
//
BITMAP bm; if (GetObject( IconInfo.hbmColor, sizeof(bm), &bm )) { //
// Save the size of the icon
//
sizeIcon.cx = bm.bmWidth; sizeIcon.cy = bm.bmHeight;
//
// Everything worked
//
bSuccess = true; }
//
// Free the bitmaps
//
DeleteObject(IconInfo.hbmMask); DeleteObject(IconInfo.hbmColor); } else { WIA_PRINTHRESULT((HRESULT_FROM_WIN32(GetLastError()),TEXT("GetIconInfo failed"))); }
return bSuccess; }
HBITMAP CreateIconThumbnail( HWND hWnd, int nWidth, int nHeight, HICON hIcon, LPCTSTR pszText ) { WIA_PUSH_FUNCTION((TEXT("CreateIconThumbnail( hWnd: 0x%p, nWidth: %d, nHeight: %d, hIcon: 0x%p, pszText: \"%s\" )"), hWnd, nWidth, nHeight, hIcon, pszText ? pszText : TEXT("") ));
//
// Initialize return value to NULL
//
HBITMAP hBmp = NULL;
//
// This will be set to true if all steps succeed.
//
bool bSuccess = false;
//
// The minimum whitespace around the icon and the text border
//
const int nIconBorder = 2;
//
// Get the DC to the window
//
HDC hDC = GetDC(hWnd); if (hDC) { //
// Get a halftone palette
//
HPALETTE hHalftonePalette = CreateHalftonePalette(hDC); if (hHalftonePalette) { //
// Initialize the bitmap information
//
BITMAPINFO BitmapInfo; ZeroMemory( &BitmapInfo, sizeof(BITMAPINFO) ); BitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); BitmapInfo.bmiHeader.biWidth = nWidth; BitmapInfo.bmiHeader.biHeight = nHeight; BitmapInfo.bmiHeader.biPlanes = 1; BitmapInfo.bmiHeader.biBitCount = 24; BitmapInfo.bmiHeader.biCompression = BI_RGB;
//
// Create the DIB section
//
PBYTE pBitmapData = NULL; hBmp = CreateDIBSection( hDC, &BitmapInfo, DIB_RGB_COLORS, (LPVOID*)&pBitmapData, NULL, 0 ); if (hBmp) { //
// Create the source dc
//
HDC hMemoryDC = CreateCompatibleDC( hDC ); if (hMemoryDC) { //
// Set up the palette
//
HPALETTE hOldPalette = SelectPalette( hMemoryDC, hHalftonePalette , 0 ); RealizePalette( hMemoryDC ); SetBrushOrgEx( hMemoryDC, 0,0, NULL );
//
// Set up the DC
//
int nOldBkMode = SetBkMode( hMemoryDC, TRANSPARENT ); COLORREF crOldTextColor = SetTextColor( hMemoryDC, GetSysColor(COLOR_WINDOWTEXT) ); DWORD dwOldLayout = SetLayout( hMemoryDC, LAYOUT_BITMAPORIENTATIONPRESERVED );
//
// Select the bitmap into the memory DC
//
HBITMAP hOldBitmap = reinterpret_cast<HBITMAP>(SelectObject( hMemoryDC, hBmp ));
//
// Get the font to use
//
HFONT hFont = GetFontFromWindow(hWnd);
//
// Select the font
//
HFONT hOldFont = reinterpret_cast<HFONT>(SelectObject( hMemoryDC, hFont ) );
//
// Ensure we have a valid icon
//
if (hIcon) { //
// Try to get the size of the icon
//
SIZE sizeIcon; if (GetIconSize( hIcon, sizeIcon )) { //
// Fill the bitmap with the window color
//
RECT rc = { 0, 0, nWidth, nHeight }; FillRect( hMemoryDC, &rc, GetSysColorBrush( COLOR_WINDOW ) );
//
// Get the text height for one line of text
//
SIZE sizeText = {0}; if (pszText) { GetTextExtentPoint32( hMemoryDC, TEXT("X"), 1, &sizeText ); }
//
// Center the icon + 1 line of text + margin in the thumbnail
// We are assuming this bitmap can actually hold an icon + text
//
int nIconTop = rc.top + (RectHeight(rc) - ( sizeIcon.cy + sizeText.cy + nIconBorder )) / 2;
//
// Draw the icon
//
DrawIconEx( hMemoryDC, (nWidth - sizeIcon.cx)/2, nIconTop, hIcon, sizeIcon.cx, sizeIcon.cy, 0, NULL, DI_NORMAL );
//
// Only compute text things if there's text to draw
//
if (pszText && *pszText) { //
// Decrease the rectangle's width by the icon border
//
InflateRect( &rc, -nIconBorder, 0 );
//
// Set the top of the text to the bottom of icon + the icon border
//
rc.top = nIconTop + sizeIcon.cy + nIconBorder;
//
// Draw the text
//
DrawTextEx( hMemoryDC, const_cast<LPTSTR>(pszText), -1, &rc, DT_CENTER|DT_END_ELLIPSIS|DT_NOPREFIX|DT_WORDBREAK, NULL ); }
//
// Everything worked OK
//
bSuccess = true; } else { WIA_ERROR((TEXT("Couldn't get an icon size"))); }
} else { WIA_ERROR((TEXT("Didn't have a valid icon"))); }
//
// Restore the dc's state
//
SelectObject( hMemoryDC, hOldFont ); SelectObject( hMemoryDC, hOldBitmap ); SelectPalette( hMemoryDC, hOldPalette , 0 ); SetBkMode( hMemoryDC, nOldBkMode ); SetTextColor( hMemoryDC, crOldTextColor ); SetLayout( hMemoryDC, dwOldLayout );
//
// Delete the compatible DC
//
DeleteDC( hMemoryDC );
} else { WIA_ERROR((TEXT("Unable to create a memory DC"))); } } else { WIA_ERROR((TEXT("Unable to create a DIB section"))); }
//
// Delete the halftone palette
//
if (hHalftonePalette) { DeleteObject( hHalftonePalette ); } } else { WIA_ERROR((TEXT("Unable to get a halftone palette"))); }
//
// Release the client DC
//
ReleaseDC( hWnd, hDC ); } else { WIA_ERROR((TEXT("Unable to get a DC"))); }
//
// Clean up in the event of failure
//
if (!bSuccess) { if (hBmp) { DeleteObject(hBmp); hBmp = NULL; } } return hBmp; } //
// Create a bitmap with an icon and optional text
//
HBITMAP CreateIconThumbnail( HWND hWnd, int nWidth, int nHeight, HINSTANCE hIconInstance, const CResId &resIconId, LPCTSTR pszText ) { //
// Assume failure
//
HBITMAP hBmp = NULL;
//
// Load the specified icon
//
HICON hIcon = (HICON)LoadImage( hIconInstance, resIconId.ResourceName(), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR ); if (hIcon) { //
// Create the thumbnail
//
hBmp = CreateIconThumbnail( hWnd, nWidth, nHeight, hIcon, pszText );
//
// Free the icon (even though MSDN doesn't mention this, it will result in a leak if you don't)
//
DestroyIcon(hIcon); }
return hBmp; }
HRESULT SaveWiaItemAudio( IWiaItem *pWiaItem, LPCTSTR pszBaseFilename, CSimpleString &strAudioFilename ) { //
// Check the arguments
//
if (!pWiaItem || !pszBaseFilename || !lstrlen(pszBaseFilename)) { return E_INVALIDARG; }
//
// Get the audio data property, if present
//
CComPtr<IWiaPropertyStorage> pWiaPropertyStorage; HRESULT hr = pWiaItem->QueryInterface( IID_IWiaPropertyStorage, (void**)(&pWiaPropertyStorage) ); if (SUCCEEDED(hr)) { PROPVARIANT PropVar[3]; PROPSPEC PropSpec[3];
PropSpec[0].ulKind = PRSPEC_PROPID; PropSpec[0].propid = WIA_IPC_AUDIO_DATA;
PropSpec[1].ulKind = PRSPEC_PROPID; PropSpec[1].propid = WIA_IPC_AUDIO_AVAILABLE;
PropSpec[2].ulKind = PRSPEC_PROPID; PropSpec[2].propid = WIA_IPC_AUDIO_DATA_FORMAT;
hr = pWiaPropertyStorage->ReadMultiple( ARRAYSIZE(PropSpec), PropSpec, PropVar ); if (SUCCEEDED(hr)) { if (PropVar[1].lVal && PropVar[0].caub.cElems) { TCHAR szFile[MAX_PATH + 4]; lstrcpyn( szFile, pszBaseFilename, ARRAYSIZE(szFile) );
//
// Figure out where the extension should go.
//
LPTSTR pszExtensionPoint = PathFindExtension(szFile);
//
// Replace the extension. If the item specifies the clsid, use it. Otherwise assume WAV
//
if (PropVar[2].vt == VT_CLSID && PropVar[2].puuid) { lstrcpy( pszExtensionPoint, TEXT(".") ); lstrcat( pszExtensionPoint, CWiaFileFormat::GetExtension(*PropVar[2].puuid) ); } else { lstrcpy( pszExtensionPoint, TEXT(".") ); lstrcat( pszExtensionPoint, TEXT("wav") ); }
//
// Save the filename for the caller
//
strAudioFilename = szFile;
//
// Open the file and save the data to the file
//
HANDLE hFile = CreateFile( szFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); if (INVALID_HANDLE_VALUE != hFile) { DWORD dwBytesWritten; if (WriteFile( hFile, PropVar[0].caub.pElems, PropVar[0].caub.cElems, &dwBytesWritten, NULL )) { // Success
} else { hr = HRESULT_FROM_WIN32(GetLastError()); } CloseHandle(hFile); } else { hr = HRESULT_FROM_WIN32(GetLastError()); } } else { hr = E_FAIL; WIA_PRINTHRESULT((hr,TEXT("There is no audio data"))); } FreePropVariantArray( ARRAYSIZE(PropVar), PropVar ); } } return hr; }
bool IsDeviceCommandSupported( IWiaItem *pWiaItem, const GUID &guidCommand ) { //
// Assume failure
//
bool bResult = false;
//
// Make sure we have a valid item
//
if (pWiaItem) { //
// Get the device capabilities enumerator
//
CComPtr<IEnumWIA_DEV_CAPS> pDeviceCapabilities; HRESULT hr = pWiaItem->EnumDeviceCapabilities( WIA_DEVICE_COMMANDS, &pDeviceCapabilities ); if (SUCCEEDED(hr)) { //
// Enumerate the capabilities
//
WIA_DEV_CAP WiaDeviceCapability; while (!bResult && S_OK == pDeviceCapabilities->Next(1, &WiaDeviceCapability, NULL)) { //
// If we have a match, set the return value to true
//
if (guidCommand == WiaDeviceCapability.guid) { bResult = true; }
//
// Clean up the allocated data in the dev caps structure
//
if (WiaDeviceCapability.bstrName) { SysFreeString(WiaDeviceCapability.bstrName); } if (WiaDeviceCapability.bstrDescription) { SysFreeString(WiaDeviceCapability.bstrDescription); } if (WiaDeviceCapability.bstrIcon) { SysFreeString(WiaDeviceCapability.bstrIcon); } if (WiaDeviceCapability.bstrCommandline) { SysFreeString(WiaDeviceCapability.bstrCommandline); } } } }
return bResult; }
HRESULT StampItemTimeOnFile( IWiaItem *pWiaItem, LPCTSTR pszFilename ) { if (!pWiaItem || !pszFilename || !lstrlen(pszFilename)) { return E_INVALIDARG; } //
// All this, just to set the stinking file time...
// Allows for the possibility of using a VT_FILETIME
// just in case we ever make the intelligent decision
// to support VT_FILETIME
//
CComPtr<IWiaPropertyStorage> pWiaPropertyStorage; HRESULT hr = pWiaItem->QueryInterface( IID_IWiaPropertyStorage, (void **)&pWiaPropertyStorage ); if (SUCCEEDED(hr)) { //
// Get the file time
//
PROPSPEC PropSpec[1] = {0}; PROPVARIANT PropVar[1] = {0};
PropSpec[0].ulKind = PRSPEC_PROPID; PropSpec[0].propid = WIA_IPA_ITEM_TIME; hr = pWiaPropertyStorage->ReadMultiple( ARRAYSIZE(PropSpec), PropSpec, PropVar ); if (SUCCEEDED(hr)) { //
// Check to see if we are using a SYSTEMTIME structure
//
if (PropVar[0].vt > VT_NULL && PropVar[0].caub.pElems && PropVar[0].caub.cElems >= (sizeof(SYSTEMTIME)>>1)) { //
// Convert the systemtime to a local filetime
//
FILETIME FileTimeLocal; if (SystemTimeToFileTime( reinterpret_cast<SYSTEMTIME*>(PropVar[0].caub.pElems), &FileTimeLocal )) { //
// Convert the local filetime to a UTC filetime
//
FILETIME FileTimeUTC; if (LocalFileTimeToFileTime( &FileTimeLocal, &FileTimeUTC )) { //
// Open the file handle
//
HANDLE hFile = CreateFile( pszFilename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if (INVALID_HANDLE_VALUE != hFile) { //
// Set the file creation time
//
if (!SetFileTime( hFile, &FileTimeUTC, NULL, NULL )) { hr = HRESULT_FROM_WIN32(GetLastError()); WIA_PRINTHRESULT((hr,TEXT("SetFileTime failed"))); } CloseHandle( hFile ); } else { hr = HRESULT_FROM_WIN32(GetLastError()); WIA_PRINTHRESULT((hr,TEXT("CreateFile failed"))); } } else { hr = HRESULT_FROM_WIN32(GetLastError()); WIA_PRINTHRESULT((hr,TEXT("FileTimeToLocalFileTime failed"))); } } else { hr = HRESULT_FROM_WIN32(GetLastError()); WIA_PRINTHRESULT((hr,TEXT("SystemTimeToFileTime failed"))); } } else if (VT_FILETIME == PropVar[0].vt) { //
// Convert the local filetime to a UTC filetime
//
FILETIME FileTimeUTC; if (LocalFileTimeToFileTime( &PropVar[0].filetime, &FileTimeUTC )) { //
// Open the file handle
//
HANDLE hFile = CreateFile( pszFilename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if (INVALID_HANDLE_VALUE != hFile) { //
// Set the file creation time
//
if (!SetFileTime( hFile, &FileTimeUTC, NULL, NULL )) { hr = HRESULT_FROM_WIN32(GetLastError()); WIA_PRINTHRESULT((hr,TEXT("SetFileTime failed"))); } CloseHandle( hFile ); } else { hr = HRESULT_FROM_WIN32(GetLastError()); WIA_PRINTHRESULT((hr,TEXT("CreateFile failed"))); } } else { hr = HRESULT_FROM_WIN32(GetLastError()); WIA_PRINTHRESULT((hr,TEXT("FileTimeToLocalFileTime failed"))); } } else { hr = E_FAIL; WIA_PRINTHRESULT((hr,TEXT("The time property is invalid"))); } } else { WIA_ERROR((TEXT("ReadMultiple on WIA_IPA_ITEM_TIME failed"))); } } else { WIA_ERROR((TEXT("QueryInterface on IWiaPropertyStorage failed"))); } return hr; }
HRESULT MoveOrCopyFile( LPCTSTR pszSrc, LPCTSTR pszTgt ) { WIA_PUSH_FUNCTION((TEXT("CDownloadImagesThreadMessage::MoveOrCopyFile( %s, %s )"), pszSrc, pszTgt )); //
// Verify the arguments
//
if (!pszSrc || !pszTgt || !lstrlen(pszSrc) || !lstrlen(pszTgt)) { return E_INVALIDARG; }
//
// Assume everything worked ok
//
HRESULT hr = S_OK;
//
// First try to move the file, since that will be lots faster
//
if (!MoveFile( pszSrc, pszTgt )) { //
// If moving the file failed, try to copy it and the delete it
//
if (CopyFile( pszSrc, pszTgt, FALSE )) { //
// We are going to ignore failures from DeleteFile. It is possible the file is legitimately in
// use, and there is probably no need to fail the entire operation because of this.
//
if (!DeleteFile( pszSrc )) { WIA_PRINTHRESULT((HRESULT_FROM_WIN32(GetLastError()),TEXT("DeleteFile failed. Ignoring failure."))); } //
// Everything worked OK
//
hr = S_OK; } else { //
// This is where we catch the main errors
//
hr = HRESULT_FROM_WIN32(GetLastError()); } } return hr; }
CSimpleString CreateTempFileName( UINT nId ) { //
// Initialize the return value to an empty string
//
CSimpleString strResult(TEXT(""));
//
// Get the temp folder path
//
TCHAR szTempDirectory[MAX_PATH] = {0}; DWORD dwResult = GetTempPath( ARRAYSIZE(szTempDirectory), szTempDirectory ); if (dwResult) { //
// Make sure the path length didn't exceed the buffer we allocated on the stack
//
if (ARRAYSIZE(szTempDirectory) >= dwResult) { //
// Get the temp file name
//
TCHAR szFileName[MAX_PATH] = {0}; if (GetTempFileName( szTempDirectory, TEXT("scw"), nId, szFileName )) { //
// Save the filename
//
strResult = szFileName; } } }
//
// Return the result. An e mpty string denotes an error.
//
return strResult; }
bool CanWiaImageBeSafelyRotated( const GUID &guidFormat, LONG nImageWidth, LONG nImageHeight ) { WIA_PUSH_FUNCTION((TEXT("WiaUiUtil::CanWiaImageBeSafelyRotated( guidFormat, %d, %d )"), nImageWidth, nImageHeight )); WIA_PRINTGUID((guidFormat,TEXT("guidFormat")));
//
// These are the image types we can possibly rotate (there may be exceptions below)
//
static const GUID *guidSafeFormats[] = { &WiaImgFmt_BMP, &WiaImgFmt_JPEG, &WiaImgFmt_PNG, &WiaImgFmt_GIF };
//
// Search for this image type
//
for (int i=0;i<ARRAYSIZE(guidSafeFormats);i++) { //
// If we've found it
//
if (*guidSafeFormats[i] == guidFormat) { //
// Handle exceptions to the rule
//
if (guidFormat == WiaImgFmt_JPEG) { //
// We can't do lossless rotation on JPG images that are not even multiples of 16 in size
//
if ((nImageWidth % 16) || (nImageHeight % 16)) { WIA_TRACE((TEXT("This image is not valid for rotation because it is not an even multiple of 16"))); return false; } }
//
// If none of the exceptions applied, return TRUE
//
WIA_TRACE((TEXT("Returning true"))); return true; } }
//
// If it is not known that we CAN rotate, we report false
//
WIA_TRACE((TEXT("Format type not found in safe list"))); return false; }
HRESULT ExploreWiaDevice( LPCWSTR pszDeviceId ) { HRESULT hr;
//
// Make sure we have a valid device id
//
if (!pszDeviceId || !lstrlenW(pszDeviceId)) { return E_INVALIDARG; }
//
// Load the shell extension's dll
//
HINSTANCE hInstWiaShellDll = LoadLibrary(TEXT("WIASHEXT.DLL")); if (hInstWiaShellDll) { //
// Get the function that creates pidls
//
WIAMAKEFULLPIDLFORDEVICE pfnMakeFullPidlForDevice = reinterpret_cast<WIAMAKEFULLPIDLFORDEVICE>(GetProcAddress(hInstWiaShellDll, "MakeFullPidlForDevice")); if (pfnMakeFullPidlForDevice) { //
// Get the device PIDL
//
LPITEMIDLIST pidlDevice = NULL; hr = pfnMakeFullPidlForDevice( const_cast<LPWSTR>(pszDeviceId), &pidlDevice ); if (SUCCEEDED(hr)) { //
// First, ask the shell to refresh any active views
//
SHChangeNotify(SHCNE_UPDATEDIR, SHCNF_IDLIST, pidlDevice, 0);
//
// Now show the folder
//
SHELLEXECUTEINFO ShellExecuteInfo = {0}; ShellExecuteInfo.cbSize = sizeof(ShellExecuteInfo); ShellExecuteInfo.fMask = SEE_MASK_IDLIST; ShellExecuteInfo.nShow = SW_SHOW; ShellExecuteInfo.lpIDList = pidlDevice; if (ShellExecuteEx( &ShellExecuteInfo )) { hr = S_OK; }
//
// Free the pidl
//
LPMALLOC pMalloc = NULL; if (SUCCEEDED(SHGetMalloc(&pMalloc)) && pMalloc) { pMalloc->Free(pidlDevice); pMalloc->Release(); } } } else { hr = E_FAIL; }
//
// Unload the DLL
//
FreeLibrary( hInstWiaShellDll ); } else { //
// Can't load the DLL
//
hr = E_FAIL; }
return hr; }
//
// Modify a combo box's drop down list so that it is
// long enough to store the longest string in the list
// Taken from TaoYuan's code in photowiz.dll and modified
// to handle ComboBoxEx32 controls
//
BOOL ModifyComboBoxDropWidth( HWND hWndCombobox ) { //
// Make sure we have a valid window
//
if (!hWndCombobox) { return FALSE; }
//
// Find out how many items are in the combobox. If there are none, don't bother resizing.
//
LRESULT lRes = SendMessage( hWndCombobox, CB_GETCOUNT, 0, 0 ); if (lRes <= 0) { return FALSE; } UINT nCount = static_cast<UINT>(lRes);
//
// We only work with fixed-height comboboxes
//
lRes = SendMessage( hWndCombobox, CB_GETITEMHEIGHT, 0, 0 ); if (lRes < 0) { return FALSE; } UINT nItemHeight = static_cast<UINT>(lRes);
//
// We will be going through to figure out the desired size of the drop down list
//
UINT nDesiredWidth = 0;
//
// Add the size of the scrollbar to the desired witdth, of there is one
//
RECT rcDropped = {0}; SendMessage( hWndCombobox, CB_GETDROPPEDCONTROLRECT, 0, reinterpret_cast<LPARAM>(&rcDropped) );
//
// Get the size of the control's window
//
RECT rcWnd = {0}; GetWindowRect( hWndCombobox, &rcWnd );
//
// If not all of the items will fit in the dropped list,
// we have to account for a vertical scrollbar
//
if (((WiaUiUtil::RectHeight(rcDropped) - GetSystemMetrics(SM_CYEDGE)*2) / nItemHeight) < nCount) { nDesiredWidth += GetSystemMetrics(SM_CXEDGE)*2 + GetSystemMetrics( SM_CXVSCROLL ); }
//
// Find the widest string
//
LONG nMaxStringLen = 0; HDC hDC = GetDC( hWndCombobox ); if (hDC) { //
// Use the control's font
//
HFONT hOldFont = NULL, hFont = reinterpret_cast<HFONT>(SendMessage(hWndCombobox,WM_GETFONT,0,0)); if (hFont) { hOldFont = SelectFont( hDC, hFont ); }
for (UINT i = 0; i < nCount; i++ ) { //
// Get the length of this item's text
//
LRESULT nLen = SendMessage( hWndCombobox, CB_GETLBTEXTLEN, i, 0 ); if (nLen > 0) { //
// Allocate a buffer for the string
//
LPTSTR pszItem = new TCHAR[nLen+1]; if (pszItem) { //
// Get the string
//
pszItem[0] = TEXT('\0'); if (SendMessage( hWndCombobox, CB_GETLBTEXT, i, reinterpret_cast<LPARAM>(pszItem) ) > 0) { //
// Measure it
//
SIZE sizeText = {0}; if (GetTextExtentPoint32( hDC, pszItem, lstrlen( pszItem ), &sizeText )) { //
// If this is the longest one, save its length
//
if (sizeText.cx > nMaxStringLen) { nMaxStringLen = sizeText.cx; } } }
//
// Free the string
//
delete[] pszItem; } } }
//
// Restore and release the DC
//
if (hOldFont) { SelectFont( hDC, hOldFont ); } ReleaseDC( hWndCombobox, hDC ); } //
// Add in the longest string's length
//
nDesiredWidth += nMaxStringLen;
//
// If this is a ComboBoxEx32, add in the width of the icon
//
TCHAR szClassName[MAX_PATH] = {0}; if (GetClassName( hWndCombobox, szClassName, ARRAYSIZE(szClassName))) { //
// Compare the classname with ComboBoxEx32
//
if (!lstrcmp(szClassName,WC_COMBOBOXEX)) { //
// Get the image list from the control
//
HIMAGELIST hImageList = reinterpret_cast<HIMAGELIST>(SendMessage( hWndCombobox, CBEM_GETIMAGELIST, 0, 0 )); if (hImageList) { //
// Get the width and add it to the desired size
//
INT nWidth=0, nHeight=0; if (ImageList_GetIconSize( hImageList, &nWidth, &nHeight )) { //
// I don't know what the margin should be, but nWidth*2
// should account for the width of icon and its margin
//
nDesiredWidth += nWidth * 2; } } } }
//
// Add in the border of the control
//
nDesiredWidth += GetSystemMetrics(SM_CXFIXEDFRAME)*2;
//
// Make sure our drop down is no wider than the current monitor
//
HMONITOR hMonitor = MonitorFromWindow( hWndCombobox, MONITOR_DEFAULTTONEAREST ); if (hMonitor) { MONITORINFO MonitorInfo = {0}; MonitorInfo.cbSize = sizeof(MonitorInfo); //
// Get the screen coordinates of this monitor
//
if (GetMonitorInfo(hMonitor, &MonitorInfo)) { //
// If the desired width is larger than the monitor, shorten it
//
if (nDesiredWidth > static_cast<UINT>(WiaUiUtil::RectWidth(MonitorInfo.rcMonitor))) { nDesiredWidth = RectWidth(MonitorInfo.rcMonitor); } } }
//
// If our size is smaller than the control's current size, grow it
//
if (static_cast<UINT>(WiaUiUtil::RectWidth(rcDropped)) < nDesiredWidth) { //
// Disable redrawing
//
SendMessage( hWndCombobox, WM_SETREDRAW, FALSE, 0 );
SendMessage( hWndCombobox, CB_SETDROPPEDWIDTH, static_cast<WPARAM>(nDesiredWidth), 0 );
//
// Allow redrawing
//
SendMessage( hWndCombobox, WM_SETREDRAW, TRUE, 0 );
//
// Force a repaint
//
InvalidateRect( hWndCombobox, NULL, FALSE ); UpdateWindow( hWndCombobox );
//
// TRUE means we actually changed it
//
return TRUE; }
return FALSE; }
static LPCTSTR s_pszComboBoxExWndProcPropName = TEXT("WiaComboBoxExWndProcPropName");
static LRESULT WINAPI ComboBoxExWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam ) { static WNDPROC s_pfnDefProc = NULL;
WNDPROC pfnWndProc = reinterpret_cast<WNDPROC>(GetProp( hWnd, s_pszComboBoxExWndProcPropName ));
if (!s_pfnDefProc) { WNDCLASS wc = {0}; GetClassInfo( GetModuleHandle(TEXT("user32.dll")), TEXT("ComboBox"), &wc ); s_pfnDefProc = wc.lpfnWndProc; } if (nMsg == WM_LBUTTONDOWN || nMsg == WM_RBUTTONDOWN) { if (s_pfnDefProc) { return CallWindowProc( s_pfnDefProc, hWnd, nMsg, wParam, lParam ); } } if (nMsg == WM_DESTROY) { RemoveProp( hWnd, s_pszComboBoxExWndProcPropName ); } if (pfnWndProc) { return CallWindowProc( pfnWndProc, hWnd, nMsg, wParam, lParam ); } else { return CallWindowProc( DefWindowProc, hWnd, nMsg, wParam, lParam ); } }
//
// This subclasses the ComboBoxEx32 to work around a bug
// that causes the list to drop down at bad times.
// Uses a window property to store the previous wndproc.
// Taken from DavidShi's code in wiashext.dll
//
void SubclassComboBoxEx( HWND hWnd ) { HWND hComboBox = FindWindowEx( hWnd, NULL, TEXT("ComboBox"), NULL ); if (hComboBox) { LONG_PTR pfnOldWndProc = SetWindowLongPtr( hComboBox, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(ComboBoxExWndProc)); SetProp( hComboBox, s_pszComboBoxExWndProcPropName, reinterpret_cast<HANDLE>(pfnOldWndProc) ); } }
HRESULT IssueWiaCancelIO( IUnknown *pUnknown ) { if (!pUnknown) { return E_POINTER; }
CComPtr<IWiaItemExtras> pWiaItemExtras; HRESULT hr = pUnknown->QueryInterface( IID_IWiaItemExtras, (void**)&pWiaItemExtras ); if (SUCCEEDED(hr)) { hr = pWiaItemExtras->CancelPendingIO(); } return hr; }
HRESULT VerifyScannerProperties( IUnknown *pUnknown ) { HRESULT hr = E_FAIL;
//
// Table of required properties
//
static const PROPID s_RequiredProperties[] = { WIA_IPS_CUR_INTENT };
//
// Make sure we have a valid item
//
if (pUnknown) { //
// Assume success at this point
//
hr = S_OK;
//
// Get the IWiaPropertyStorage interface
//
CComPtr<IWiaPropertyStorage> pWiaPropertyStorage; hr = pUnknown->QueryInterface(IID_IWiaPropertyStorage, (void**)&pWiaPropertyStorage); if (SUCCEEDED(hr)) { //
// Loop through each property and make sure it exists
// Break out if hr != S_OK
//
for (int i=0;i<ARRAYSIZE(s_RequiredProperties) && S_OK==hr;i++) { //
// Prepare the propspec
//
PROPSPEC PropSpec = {0}; PropSpec.ulKind = PRSPEC_PROPID; PropSpec.propid = s_RequiredProperties[i];
//
// Attempt to get the property attributes
//
ULONG nAccessFlags = 0; PROPVARIANT PropVariant = {0}; hr = pWiaPropertyStorage->GetPropertyAttributes( 1, &PropSpec, &nAccessFlags, &PropVariant ); if (SUCCEEDED(hr)) { //
// Prevent a leak
//
PropVariantClear(&PropVariant);
//
// If everything is OK so far
//
if (S_OK == hr) { //
// Zero out the structure
//
PropVariantInit(&PropVariant);
//
// Attempt to read the actual value
//
hr = pWiaPropertyStorage->ReadMultiple( 1, &PropSpec, &PropVariant ); if (SUCCEEDED(hr)) { //
// Free the actual value
//
PropVariantClear(&PropVariant); } } } } } }
//
// S_FALSE means a property doesn't exist, so change this to an error
//
if (S_FALSE == hr) { hr = E_FAIL; }
//
// All done
//
return hr; }
CSimpleString GetErrorTextFromHResult( HRESULT hr ) { CSimpleString strResult; LPTSTR szErrMsg = NULL; FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast<LPTSTR>(&szErrMsg), 0, NULL ); if (szErrMsg) { strResult = szErrMsg; LocalFree( szErrMsg ); } return strResult; }
} // End namespace WiaUiUtil
|