|
|
/*++
Copyright (c) 1990-1998, Microsoft Corporation All rights reserved.
Module Name:
dlgs.c
Abstract:
This module contains the common functions for the Win32 common dialogs.
Revision History:
--*/
// precompiled headers
#include "precomp.h"
#pragma hdrstop
#include "util.h"
//
// Global Variables.
//
extern BOOL bInitializing; extern DWORD g_tlsiExtError;
//
// Function Prototypes.
//
LONG RgbInvertRgb( LONG rgbOld);
const struct _ERRORMAP { DWORD dwCommDlgError; DWORD dwWin32Error; } ERRORMAP[] = { { CDERR_INITIALIZATION , ERROR_INVALID_PARAMETER}, { PDERR_INITFAILURE , ERROR_INVALID_PARAMETER}, { CDERR_STRUCTSIZE , ERROR_INVALID_PARAMETER}, { CDERR_NOTEMPLATE , ERROR_INVALID_PARAMETER}, { CDERR_NOHINSTANCE , ERROR_INVALID_PARAMETER}, { CDERR_NOHOOK , ERROR_INVALID_PARAMETER}, { CDERR_MEMALLOCFAILURE , ERROR_OUTOFMEMORY}, { CDERR_LOCKRESFAILURE , ERROR_INVALID_HANDLE}, { CDERR_DIALOGFAILURE , E_FAIL}, { PDERR_SETUPFAILURE , ERROR_INVALID_PARAMETER}, { PDERR_RETDEFFAILURE , ERROR_INVALID_PARAMETER}, { FNERR_BUFFERTOOSMALL , ERROR_INSUFFICIENT_BUFFER}, { FRERR_BUFFERLENGTHZERO, ERROR_INSUFFICIENT_BUFFER}, { FNERR_INVALIDFILENAME , ERROR_INVALID_NAME}, { PDERR_NODEFAULTPRN , E_FAIL}, { CFERR_NOFONTS , E_FAIL}, { CFERR_MAXLESSTHANMIN , ERROR_INVALID_PARAMETER}, };
////////////////////////////////////////////////////////////////////////////
//
// StoreExtendedError
//
// Stores an extended error code for the next call to
// CommDlgExtendedError.
//
////////////////////////////////////////////////////////////////////////////
void StoreExtendedError( DWORD dwError) { int i; for (i=0; i < ARRAYSIZE(ERRORMAP); i++) { if (ERRORMAP[i].dwCommDlgError == dwError) { SetLastError(ERRORMAP[i].dwWin32Error); break; } } TlsSetValue(g_tlsiExtError, UlongToPtr(dwError)); }
////////////////////////////////////////////////////////////////////////////
//
// GetStoredExtendedError
//
// Retieves the stored extended error code.
//
////////////////////////////////////////////////////////////////////////////
DWORD GetStoredExtendedError(void) { DWORD dwError;
dwError = PtrToUlong(TlsGetValue(g_tlsiExtError));
return (dwError); }
////////////////////////////////////////////////////////////////////////////
//
// CommDlgExtendedError
//
// Provides additional information about dialog failure.
// This should be called immediately after failure.
//
// Returns: LO word - error code
// HI word - error specific info
//
////////////////////////////////////////////////////////////////////////////
DWORD WINAPI CommDlgExtendedError() { return (GetStoredExtendedError()); }
////////////////////////////////////////////////////////////////////////////
//
// HourGlass
//
// Turn hourglass on or off.
//
// bOn - specifies ON or OFF
//
////////////////////////////////////////////////////////////////////////////
VOID HourGlass( BOOL bOn) { //
// Change cursor to hourglass.
//
if (!bInitializing) { if (!bMouse) { ShowCursor(bCursorLock = bOn); } SetCursor(LoadCursor(NULL, bOn ? IDC_WAIT : IDC_ARROW)); } }
////////////////////////////////////////////////////////////////////////////
//
// LoadAlterBitmap
//
// Loads a bitmap given its name and gives all the pixels that are
// a certain color a new color.
//
// Returns: NULL - failed
// handle to the bitmap loaded - success
//
////////////////////////////////////////////////////////////////////////////
HBITMAP WINAPI LoadAlterBitmap( int id, DWORD rgbReplace, DWORD rgbInstead) { LPBITMAPINFOHEADER qbihInfo; HDC hdcScreen; BOOL fFound; HANDLE hresLoad; HANDLE hres; LPLONG qlng; DWORD *qlngReplace; // points to bits that are replaced
LPBYTE qbBits; HANDLE hbmp; LPBITMAPINFOHEADER lpBitmapInfo; UINT cbBitmapSize;
hresLoad = FindResource(g_hinst, MAKEINTRESOURCE(id), RT_BITMAP); if (hresLoad == HNULL) { return (HNULL); } hres = LoadResource(g_hinst, hresLoad); if (hres == HNULL) { return (HNULL); }
//
// Lock the bitmap data and make a copy of it for the mask and the
// bitmap.
//
cbBitmapSize = SizeofResource(g_hinst, hresLoad); lpBitmapInfo = (LPBITMAPINFOHEADER)LockResource(hres);
qbihInfo = (LPBITMAPINFOHEADER)LocalAlloc(LPTR, cbBitmapSize);
if ((lpBitmapInfo == NULL) || (qbihInfo == NULL)) { return (NULL); }
memcpy((TCHAR *)qbihInfo, (TCHAR *)lpBitmapInfo, cbBitmapSize);
//
// Get a pointer into the color table of the bitmaps, cache the
// number of bits per pixel.
//
rgbReplace = RgbInvertRgb(rgbReplace); rgbInstead = RgbInvertRgb(rgbInstead);
qlng = (LPLONG)((LPSTR)(qbihInfo) + qbihInfo->biSize);
fFound = FALSE; while (!fFound) { if (*qlng == (LONG)rgbReplace) { fFound = TRUE; qlngReplace = (DWORD *)qlng; *qlng = (LONG)rgbInstead; } qlng++; }
//
// First skip over the header structure.
//
qbBits = (LPBYTE)(qbihInfo + 1);
//
// Skip the color table entries, if any.
//
qbBits += (1 << (qbihInfo->biBitCount)) * sizeof(RGBQUAD);
//
// Create a color bitmap compatible with the display device.
//
hdcScreen = GetDC(HNULL); if (hdcScreen != HNULL) { hbmp = CreateDIBitmap( hdcScreen, qbihInfo, (LONG)CBM_INIT, qbBits, (LPBITMAPINFO)qbihInfo, DIB_RGB_COLORS ); ReleaseDC(HNULL, hdcScreen); }
//
// Reset color bits to original value.
//
*qlngReplace = (LONG)rgbReplace;
LocalFree(qbihInfo); return (hbmp); }
////////////////////////////////////////////////////////////////////////////
//
// RgbInvertRgb
//
// Reverses the byte order of the RGB value (for file format).
//
// Returns the new color value (RGB to BGR).
//
////////////////////////////////////////////////////////////////////////////
LONG RgbInvertRgb( LONG rgbOld) { LONG lRet; BYTE R, G, B;
R = GetRValue(rgbOld); G = GetGValue(rgbOld); B = GetBValue(rgbOld);
lRet = (LONG)RGB(B, G, R);
return (lRet); }
////////////////////////////////////////////////////////////////////////////
//
// HbmpLoadBmp
//
// Loads in a bitmap.
//
// Returns: Bitmap handle - success
// HNULL - failure
//
////////////////////////////////////////////////////////////////////////////
#if 0
HBITMAP HbmpLoadBmp( WORD bmp) { HBITMAP hbmp; CHAR szBitmap[cbResNameMax];
hbmp = HNULL; if (LoadString(g_hinst, bmp, (LPTSTR)szBitmap, cbResNameMax - 1)) { hbmp = LoadBitmap(g_hinst, (LPCTSTR)szBitmap); } return (hbmp); } #endif
////////////////////////////////////////////////////////////////////////////
//
// AddNetButton
//
// Attempts to add a network button to the open, save, or print dialogs.
//
// hDlg - dialog to add button to
// hInstance - instance handle for dlg
// dyBottomMargin - DUs to bottom edge
//
////////////////////////////////////////////////////////////////////////////
#define xDUsToPels(DUs, lDlgBaseUnits) \
(int)(((DUs) * (int)LOWORD((lDlgBaseUnits))) / 4)
#define yDUsToPels(DUs, lDlgBaseUnits) \
(int)(((DUs) * (int)HIWORD((lDlgBaseUnits))) / 8)
VOID AddNetButton( HWND hDlg, HANDLE hInstance, int dyBottomMargin, BOOL bAddAccel, BOOL bTryLowerRight, BOOL bTryLowerLeft) { LONG lDlgBaseUnits; RECT rcDlg, rcCtrl, rcTmp; LONG xButton, yButton; LONG dxButton, dyButton; LONG dxDlgFrame, dyDlgFrame; LONG yDlgHeight, xDlgWidth; HWND hwndButton, hCtrl, hLastCtrl, hTmp, hSave; HFONT hFont; POINT ptTopLeft, ptTopRight, ptCenter, ptBtmLeft, ptBtmRight, ptTopLeftTmp; TCHAR szNetwork[MAX_PATH];
//
// Make sure a network button (psh14) doesn't already exist in
// the dialog.
//
if (GetDlgItem(hDlg, psh14)) { return; }
//
// Get dialog coordinate info.
//
lDlgBaseUnits = GetDialogBaseUnits();
dxDlgFrame = GetSystemMetrics(SM_CXDLGFRAME); dyDlgFrame = GetSystemMetrics(SM_CYDLGFRAME);
GetWindowRect(hDlg, &rcDlg);
rcDlg.left += dxDlgFrame; rcDlg.right -= dxDlgFrame; rcDlg.top += dyDlgFrame + GetSystemMetrics(SM_CYCAPTION); rcDlg.bottom -= dyDlgFrame;
//
// Get the OK button.
//
if (!(hCtrl = GetDlgItem(hDlg, IDOK))) { return; }
GetWindowRect(hCtrl, &rcCtrl);
ptTopLeft.x = rcCtrl.left; ptTopLeft.y = rcCtrl.top;
//
// Make sure the OK button isn't outside the dialog.
//
if (!PtInRect(&rcDlg, ptTopLeft)) { //
// Try the CANCEL button.
//
if (!(hCtrl = GetDlgItem(hDlg, IDCANCEL))) { //
// Both OK and CANCEL do not exist, so return.
//
return; }
//
// The check for the Cancel button outside the dialog is handled
// below.
//
GetWindowRect(hCtrl, &rcCtrl); } hSave = hCtrl;
#ifdef UNICODE
//
// Get the full hDlg value if coming from WOW.
//
if (IS_INTRESOURCE(hDlg)) { HWND hNewDlg = GetParent(hCtrl);
if (hDlg == (HWND)LOWORD(hNewDlg)) { hDlg = hNewDlg; } } #endif
//
// Save the coordinate info of the button.
//
dxButton = rcCtrl.right - rcCtrl.left; dyButton = rcCtrl.bottom - rcCtrl.top;
xButton = rcCtrl.left; yButton = rcCtrl.bottom + yDUsToPels(4, lDlgBaseUnits);
yDlgHeight = rcDlg.bottom - yDUsToPels(dyBottomMargin, lDlgBaseUnits);
//
// Try to insert the network button in the lower right corner
// of dialog box.
//
if (bTryLowerRight && (hTmp = GetDlgItem(hDlg, cmb2))) { //
// See if the network button can be inserted in the
// lower right corner of the dialog box.
//
hLastCtrl = hCtrl; GetWindowRect(hTmp, &rcTmp); yButton = rcTmp.top;
//
// Set the coordinates of the new button.
//
ptTopLeft.x = ptBtmLeft.x = xButton; ptTopLeft.y = ptTopRight.y = yButton; ptTopRight.x = ptBtmRight.x = xButton + dxButton; ptBtmLeft.y = ptBtmRight.y = yButton + dyButton; ptCenter.x = xButton + dxButton / 2; ptCenter.y = yButton + dyButton / 2; ScreenToClient(hDlg, (LPPOINT)&ptTopLeft); ScreenToClient(hDlg, (LPPOINT)&ptBtmLeft); ScreenToClient(hDlg, (LPPOINT)&ptTopRight); ScreenToClient(hDlg, (LPPOINT)&ptBtmRight); ScreenToClient(hDlg, (LPPOINT)&ptCenter);
//
// See if the new button is over any other buttons.
//
if (((yButton + dyButton) < yDlgHeight) && ((ChildWindowFromPoint(hDlg, ptTopLeft) == hDlg) && (ChildWindowFromPoint(hDlg, ptTopRight) == hDlg) && (ChildWindowFromPoint(hDlg, ptCenter) == hDlg) && (ChildWindowFromPoint(hDlg, ptBtmLeft) == hDlg) && (ChildWindowFromPoint(hDlg, ptBtmRight) == hDlg))) { //
// If the last control is the OK button and there is a
// HELP button, then the last control should be the
// HELP button.
//
if ((hLastCtrl == GetDlgItem(hDlg, IDOK)) && (hCtrl = GetDlgItem(hDlg, pshHelp))) { GetWindowRect(hCtrl, &rcCtrl); ptTopLeftTmp.x = rcCtrl.left; ptTopLeftTmp.y = rcCtrl.top;
//
// Make sure the HELP button isn't outside the dialog
// and then set the last control to be the HELP button.
//
if (PtInRect(&rcDlg, ptTopLeftTmp)) { hLastCtrl = hCtrl; } }
//
// If the last control is still the OK button and there is a
// CANCEL button, then the last control should be the
// CANCEL button.
//
if ((hLastCtrl == GetDlgItem(hDlg, IDOK)) && (hCtrl = GetDlgItem(hDlg, IDCANCEL))) { GetWindowRect(hCtrl, &rcCtrl); ptTopLeftTmp.x = rcCtrl.left; ptTopLeftTmp.y = rcCtrl.top;
//
// Make sure the CANCEL button isn't outside the dialog
// and then set the last control to be the CANCEL button.
//
if (PtInRect(&rcDlg, ptTopLeftTmp)) { hLastCtrl = hCtrl; } }
goto FoundPlace; }
//
// Reset yButton.
//
yButton = rcCtrl.bottom + yDUsToPels(4, lDlgBaseUnits); }
//
// Try to insert the network button vertically below the other
// control buttons.
//
while (hCtrl != NULL) { //
// Move vertically down and see if there is space.
//
hLastCtrl = hCtrl; GetWindowRect(hCtrl, &rcCtrl); yButton = rcCtrl.bottom + yDUsToPels(4, lDlgBaseUnits);
//
// Make sure there is still room in the dialog.
//
if ((yButton + dyButton) > yDlgHeight) { //
// No space.
//
break; }
//
// Set the coordinates of the new button.
//
ptTopLeft.x = ptBtmLeft.x = xButton; ptTopLeft.y = ptTopRight.y = yButton; ptTopRight.x = ptBtmRight.x = xButton + dxButton; ptBtmLeft.y = ptBtmRight.y = yButton + dyButton; ptCenter.x = xButton + dxButton / 2; ptCenter.y = yButton + dyButton / 2; ScreenToClient(hDlg, (LPPOINT)&ptTopLeft); ScreenToClient(hDlg, (LPPOINT)&ptBtmLeft); ScreenToClient(hDlg, (LPPOINT)&ptTopRight); ScreenToClient(hDlg, (LPPOINT)&ptBtmRight); ScreenToClient(hDlg, (LPPOINT)&ptCenter);
//
// See if the new button is over any other buttons.
//
if (((hCtrl = ChildWindowFromPoint(hDlg, ptTopLeft)) == hDlg) && ((hCtrl = ChildWindowFromPoint(hDlg, ptTopRight)) == hDlg) && ((hCtrl = ChildWindowFromPoint(hDlg, ptCenter)) == hDlg) && ((hCtrl = ChildWindowFromPoint(hDlg, ptBtmLeft)) == hDlg) && ((hCtrl = ChildWindowFromPoint(hDlg, ptBtmRight)) == hDlg)) { goto FoundPlace; } }
//
// Try to insert the network button in the lower left corner of
// the dialog box.
//
if (bTryLowerLeft) { //
// Get the width of the dialog to make sure the button doesn't
// go off the side of the dialog.
//
xDlgWidth = rcDlg.right - xDUsToPels(FILE_RIGHT_MARGIN, lDlgBaseUnits);
//
// Use the OK or CANCEL button saved earlier to get the size of
// the buttons.
//
hCtrl = hSave;
//
// Start at the far left of the dialog.
//
// NOTE: We know that hCtrl is not NULL at this point because
// otherwise we would have returned earlier.
//
// The print dialogs have a left margin of 8.
//
GetWindowRect(hCtrl, &rcCtrl); xButton = rcDlg.left + xDUsToPels(FILE_LEFT_MARGIN + 3, lDlgBaseUnits); yButton = rcCtrl.top;
while (1) { hLastCtrl = hCtrl;
//
// Make sure there is still room in the dialog.
//
if ((xButton + dxButton) > xDlgWidth) { //
// No space.
//
break; }
//
// Set the coordinates of the new button.
//
ptTopLeft.x = ptBtmLeft.x = xButton; ptTopLeft.y = ptTopRight.y = yButton; ptTopRight.x = ptBtmRight.x = xButton + dxButton; ptBtmLeft.y = ptBtmRight.y = yButton + dyButton; ptCenter.x = xButton + dxButton / 2; ptCenter.y = yButton + dyButton / 2; ScreenToClient(hDlg, (LPPOINT)&ptTopLeft); ScreenToClient(hDlg, (LPPOINT)&ptBtmLeft); ScreenToClient(hDlg, (LPPOINT)&ptTopRight); ScreenToClient(hDlg, (LPPOINT)&ptBtmRight); ScreenToClient(hDlg, (LPPOINT)&ptCenter);
//
// See if the new button is over any other buttons.
//
if ( ( ((hCtrl = ChildWindowFromPoint(hDlg, ptTopLeft)) == hDlg) && ((hCtrl = ChildWindowFromPoint(hDlg, ptTopRight)) == hDlg) && ((hCtrl = ChildWindowFromPoint(hDlg, ptCenter)) == hDlg) && ((hCtrl = ChildWindowFromPoint(hDlg, ptBtmLeft)) == hDlg) && ((hCtrl = ChildWindowFromPoint(hDlg, ptBtmRight)) == hDlg) ) ) { //
// If the last control is the OK button and there is a
// HELP button, then the last control should be the
// HELP button.
//
if ((hLastCtrl == GetDlgItem(hDlg, IDOK)) && (hCtrl = GetDlgItem(hDlg, pshHelp))) { GetWindowRect(hCtrl, &rcCtrl); ptTopLeftTmp.x = rcCtrl.left; ptTopLeftTmp.y = rcCtrl.top;
//
// Make sure the HELP button isn't outside the dialog
// and then set the last control to be the HELP button.
//
if (PtInRect(&rcDlg, ptTopLeftTmp)) { hLastCtrl = hCtrl; } }
//
// If the last control is still the OK button and there is a
// CANCEL button, then the last control should be the
// CANCEL button.
//
if ((hLastCtrl == GetDlgItem(hDlg, IDOK)) && (hCtrl = GetDlgItem(hDlg, IDCANCEL))) { GetWindowRect(hCtrl, &rcCtrl); ptTopLeftTmp.x = rcCtrl.left; ptTopLeftTmp.y = rcCtrl.top;
//
// Make sure the CANCEL button isn't outside the dialog
// and then set the last control to be the CANCEL button.
//
if (PtInRect(&rcDlg, ptTopLeftTmp)) { hLastCtrl = hCtrl; } }
goto FoundPlace; }
//
// Make sure we encountered another control and that we
// didn't go off the end of the dialog.
//
if (!hCtrl) { break; }
//
// Move over to the right and see if there is space.
//
GetWindowRect(hCtrl, &rcCtrl); xButton = rcCtrl.right + xDUsToPels(4, lDlgBaseUnits); } }
return;
FoundPlace:
xButton = ptTopLeft.x; yButton = ptTopLeft.y;
//If it a mirrored Dlg then the direction will be to the right.
if (IS_WINDOW_RTL_MIRRORED(hDlg)) xButton -= dxButton;
#ifndef UNICODE
//
// For non-localized apps that don't include the network button as part
// of their template, don't add a Far East one because the characters
// will not be displayed correctly.
//
{ #define NetworkButtonText TEXT("Network...")
#define NetworkButtonTextAccel TEXT("Net&work...")
CPINFO cpinfo;
if ((GetCPInfo(CP_ACP, &cpinfo)) && (cpinfo.MaxCharSize > 1)) { TEXTMETRIC tm; HFONT hPrevFont; HWND hIDOK = GetDlgItem(hDlg, IDOK); HDC hDC = GetDC(hIDOK);
hFont = (HFONT)SendMessage(hIDOK, WM_GETFONT, 0, 0L); if (hFont != NULL) { hPrevFont = SelectObject(hDC, hFont); GetTextMetrics(hDC, &tm); SelectObject(hDC, hPrevFont); ReleaseDC(hIDOK, hDC);
if (tm.tmCharSet == ANSI_CHARSET) { lstrcpy( szNetwork, bAddAccel ? NetworkButtonTextAccel : NetworkButtonText ); goto CreateNetworkButton; } } } } #endif
if (CDLoadString( g_hinst, (bAddAccel ? iszNetworkButtonTextAccel : iszNetworkButtonText), (LPTSTR)szNetwork, MAX_PATH )) { #ifndef UNICODE
CreateNetworkButton: #endif
hwndButton = CreateWindow( TEXT("button"), szNetwork, WS_VISIBLE | WS_CHILD | WS_GROUP | WS_TABSTOP | BS_PUSHBUTTON, xButton, yButton, dxButton, dyButton, hDlg, NULL, hInstance, NULL );
if (hwndButton != NULL) { SetWindowLong(hwndButton, GWL_ID, psh14); SetWindowPos( hwndButton, hLastCtrl, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE ); hFont = (HFONT)SendDlgItemMessage(hDlg, IDOK, WM_GETFONT, 0, 0L); SendMessage(hwndButton, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE,0)); } } }
////////////////////////////////////////////////////////////////////////////
//
// IsNetworkInstalled
//
////////////////////////////////////////////////////////////////////////////
BOOL IsNetworkInstalled() { if (GetSystemMetrics(SM_NETWORK) & RNC_NETWORKS) { return (TRUE); } else { return (FALSE); } }
#ifdef WINNT
////////////////////////////////////////////////////////////////////////////
//
// Ssync_ANSI_UNICODE_Struct_For_WOW (This is exported for WOW)
//
// For WOW support on NT only.
//
// When a 16-bit app calls one of the comdlg API's, WOW thunks the 16-bit
// comdlg struct passed by the app to a 32-bit ANSI struct. Comdlg32 code
// then thunks the 32-bit ANSI struct into a UNICODE struct. This scheme
// creates a problem for WOW apps because on Win3.1, the app and comdlg16
// share the same structure. When either updates the struct, the other is
// aware of the change.
//
// This function allows us to sychronize the UNICODE struct with the app's
// 16-bit struct & vice versa from WOW.
//
////////////////////////////////////////////////////////////////////////////
VOID Ssync_ANSI_UNICODE_Struct_For_WOW( HWND hDlg, BOOL fDirection, DWORD dwID) { switch (dwID) { case ( WOW_CHOOSECOLOR ) : { Ssync_ANSI_UNICODE_CC_For_WOW(hDlg, fDirection); break; } case ( WOW_CHOOSEFONT ) : { Ssync_ANSI_UNICODE_CF_For_WOW(hDlg, fDirection); break; } case ( WOW_OPENFILENAME ) : { Ssync_ANSI_UNICODE_OFN_For_WOW(hDlg, fDirection); break; } case ( WOW_PRINTDLG ) : { Ssync_ANSI_UNICODE_PD_For_WOW(hDlg, fDirection); break; }
// case not needed for FINDREPLACE
} }
#endif
#ifdef WX86
////////////////////////////////////////////////////////////////////////////
//
// Wx86GetX86Callback
//
// Creates a RISC-callable alias for a x86 hook function pointer.
//
// lpfnHook - x86 address of hook
//
// Returns a function pointer which can be called from RISC.
//
////////////////////////////////////////////////////////////////////////////
PVOID Wx86GetX86Callback( PVOID lpfnHook) { if (!lpfnHook) { return (NULL); }
if (!pfnAllocCallBx86) { HMODULE hMod;
if (!Wx86CurrentTib()) { //
// Wx86 is not running in this thread. Assume a RISC app has
// passed a bad flag value and that lpfnHook is already a RISC
// function pointer.
//
return (lpfnHook); }
hMod = GetModuleHandle(TEXT("wx86.dll")); if (hMod == NULL) { //
// Wx86 is running, but wx86.dll is not loaded! This should
// never happen, but if it does, assume lpfnHook is already a
// RISC pointer.
//
return (lpfnHook); } pfnAllocCallBx86 = (PALLOCCALLBX86)GetProcAddress( hMod, "AllocCallBx86" ); if (!pfnAllocCallBx86) { //
// Something has gone terribly wrong!
//
return (lpfnHook); } }
//
// Call into Wx86.dll to create a RISC-to-x86 callback which takes
// 4 parameters and has no logging.
//
return (*pfnAllocCallBx86)(lpfnHook, 4, NULL, NULL); }
#endif
////////////////////////////////////////////////////////////////////////////
//
// CDLoadString
//
////////////////////////////////////////////////////////////////////////////
int CDLoadString(HINSTANCE hInstance, UINT uID, LPTSTR lpBuffer, int nBufferMax) { return CDLoadStringEx(CP_ACP, hInstance, uID, lpBuffer, nBufferMax); }
// CDLoadStringEx takes a codepage, so we can store unicode strings in the resource file
int CDLoadStringEx(UINT cp, HINSTANCE hInstance, UINT uID, LPTSTR lpBuffer, int nBufferMax) { HRSRC hResInfo; int cch = 0; LPWSTR lpwsz; LANGID LangID;
if (!GET_BIDI_LOCALIZED_SYSTEM_LANGID(NULL)) { #ifdef WINNT
return LoadString(hInstance, uID, lpBuffer, nBufferMax); #else
lpwsz = (LPWSTR) LocalAlloc(NONZEROLPTR, nBufferMax * sizeof(WCHAR)); if (lpwsz) { int iRet; LoadStringWrapW(hInstance, uID, lpwsz, nBufferMax); iRet = WideCharToMultiByte(cp, 0, lpwsz, -1, lpBuffer, nBufferMax, NULL, NULL); LocalFree(lpwsz); return iRet; } return 0; #endif
}
LangID = (LANGID)TlsGetValue(g_tlsLangID);
if (!LangID || MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL) == LangID) { return LoadString(hInstance, uID, lpBuffer, nBufferMax); }
if (!lpBuffer || (nBufferMax-- == 0)) return 0;
// String Tables are broken up into 16 string resources. Find the resource
// containing the string we are interested in.
if (hResInfo = FindResourceExFallback(hInstance, RT_STRING, MAKEINTRESOURCE((uID>>4)+1), LangID)) {
// Load the resource. Note LoadResource returns an address.
if (lpwsz = (LPWSTR)LoadResource(hInstance, hResInfo)) { // Move past the other strings in this resource.
// (16 strings in a segment -> & 0x0F)
for (uID %= 16; uID; uID--) { lpwsz += *lpwsz + 1; } cch = min(*lpwsz, nBufferMax - 1); #ifdef UNICODE
// Copy the string into the buffer;
memcpy(lpBuffer, lpwsz+1, cch*sizeof(WCHAR)); #else
// Copy the string into the buffer, converting to Ansi.
cch= WideCharToMultiByte( CP_ACP, 0, lpwsz+1, cch, lpBuffer, cch, NULL, NULL); #endif
} }
lpBuffer[cch] = 0; return cch; }
#define ENGLISH_APP 0
#define MIRRORED_APP 1
#define BIDI_APP 2
DWORD GetAppType(HWND hWnd) { DWORD dwExStyle = 0; HWND hWndT = hWnd; DWORD dwAppType = ENGLISH_APP;
#ifdef CHECK_OWNER
//Check the window and its owners.
while (!dwExStyle && hWndT) { dwExStyle = GetWindowLongA(hWndT, GWL_EXSTYLE) & (WS_EX_RIGHT | WS_EX_RTLREADING | RTL_MIRRORED_WINDOW); hWndT = GetWindow(hWndT, GW_OWNER); }
if (!dwExStyle) { #endif
//If we still did not find then check the parents.
hWndT = hWnd; while (!dwExStyle && hWndT) { dwExStyle = GetWindowLongA(hWndT, GWL_EXSTYLE) & (WS_EX_RIGHT | WS_EX_RTLREADING | RTL_MIRRORED_WINDOW); hWndT = GetParent(hWndT); } #ifdef CHECK_OWNER
} #endif
if (dwExStyle & RTL_MIRRORED_WINDOW) { dwAppType = MIRRORED_APP; } else if (dwExStyle & (WS_EX_RIGHT | WS_EX_RTLREADING)) { dwAppType = BIDI_APP; }
return dwAppType; }
DWORD GetTemplateType(HANDLE hDlgTemplate) { DWORD dwExStyle = 0; DWORD dwAppType = ENGLISH_APP; LPDLGTEMPLATE pDlgTemplate;
pDlgTemplate = (LPDLGTEMPLATE)LockResource(hDlgTemplate); if (pDlgTemplate) { if (((LPDLGTEMPLATEEX) pDlgTemplate)->wSignature == 0xFFFF) { dwExStyle = ((LPDLGTEMPLATEEX) pDlgTemplate)->dwExStyle; } else { dwExStyle = pDlgTemplate->dwExtendedStyle; } }
if (dwExStyle & RTL_MIRRORED_WINDOW) { dwAppType = MIRRORED_APP; } else if (dwExStyle & (WS_EX_RIGHT | WS_EX_RTLREADING)) { dwAppType = BIDI_APP; }
return dwAppType; }
LANGID GetDialogLanguage(HWND hwndOwner, HANDLE hDlgTemplate) { LANGID LangID = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL); DWORD dwType;
if (GET_BIDI_LOCALIZED_SYSTEM_LANGID(&LangID)) { if (hDlgTemplate == NULL) { dwType = GetAppType(hwndOwner); } else { dwType = GetTemplateType(hDlgTemplate); }
switch (dwType) { case ENGLISH_APP : LangID = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US); break;
case MIRRORED_APP: LangID = MAKELANGID(PRIMARYLANGID(LangID), SUBLANG_DEFAULT); break;
case BIDI_APP : LangID = MAKELANGID(PRIMARYLANGID(LangID), SUBLANG_SYS_DEFAULT); break; } } return LangID; }
|