home *** CD-ROM | disk | FTP | other *** search
/ Team Palmtops 7 / Palmtops_numero07.iso / WinCE / SDKWindowsCE / HandHeldPCPro30 / sdk.exe / Jupiter SDK / data1.cab / MFC / src / wcealt.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1999-02-19  |  40.2 KB  |  1,423 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12. #include <ctype.h>
  13.  
  14. wchar_t* wce_AsciiToWide(wchar_t* ws, const char* s)
  15. {
  16.     wchar_t* pszSave = ws;
  17.     while(*s) 
  18.     {
  19.         *ws = (wchar_t) *s;
  20.         s++;
  21.         ws++;
  22.     }
  23.     *ws = 0;
  24.  
  25.     return pszSave;
  26. }
  27.  
  28. wchar_t* wce_AsciiToWide(const char* s)
  29. {
  30.     TCHAR *ws = new TCHAR[strlen(s)+1];
  31.     if(s == NULL)
  32.     {
  33.         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  34.         return NULL;
  35.     }
  36.     
  37.     return wce_AsciiToWide(ws, s);
  38. }
  39.  
  40.  
  41. int wce_wsprintfA(LPSTR szBuf, LPCSTR szFormat, UINT nArg);
  42.  
  43. // NOTE: Required by WCSTOD.OBJ in LIBC.LIB.
  44. extern "C" int WINAPI wctomb(char *s, wchar_t wchar)
  45. {
  46.     *s = (char)wchar;
  47.     return sizeof(char);
  48. }
  49.  
  50.  
  51. LPSTR wce_T2CAHelper(LPSTR lpszDest, LPCTSTR lpcszSrc)
  52. {
  53.     LPSTR lpszReturn = lpszDest;
  54.     LPTSTR lpszSrc = (LPTSTR)lpcszSrc;
  55.     if ((lpszSrc != NULL) && (lpszDest != NULL))
  56.     {
  57.         do {
  58.             *lpszDest++ = (char) *lpszSrc;
  59.         } while(*lpszSrc++);
  60.     }
  61.     return lpszReturn;
  62. }
  63.  
  64. FARPROC wce_GetProcAddress(HMODULE hModule, LPCSTR lpProcName)
  65. {
  66.     TCHAR szProcName[256] = _T("");
  67.     wce_AsciiToWide(szProcName, lpProcName);
  68.     return GetProcAddressW(hModule, szProcName);
  69. }
  70.  
  71. BOOL wce_SystemParametersInfo(UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni)
  72. {
  73.     ASSERT(uiAction == SPI_GETWORKAREA);
  74.     ASSERT(uiParam == NULL);
  75.     ASSERT(fWinIni == NULL);
  76.  
  77.     // making assumption that pvParam is a CRect* (see call to SystemParametersInfo in wincore.cpp)
  78.     CRect* pRect = (CRect*)pvParam; 
  79.     pRect->SetRect(0, 0, 
  80.         wce_GetSystemMetrics(SM_CXSCREEN), 
  81.         wce_GetSystemMetrics(SM_CYSCREEN));
  82.     return TRUE;
  83. }
  84.  
  85. HMODULE wce_LoadLibraryA(LPCSTR lpLibFileName)
  86. {
  87.     HMODULE hInst           = 0;
  88.     wchar_t szDLL[MAX_PATH] = _T("");
  89.  
  90.     wce_AsciiToWide(szDLL, lpLibFileName);
  91.     hInst = LoadLibraryW(szDLL);
  92.  
  93.     return (HMODULE)hInst;
  94. }                                            
  95.  
  96. BOOL wce_WinHelp(HWND hWndMain, LPCTSTR lpszHelpPath, UINT uCommand, DWORD dwData)
  97. {
  98.     TCHAR szHelpPathEx[MAX_PATH*2] = _T("");
  99.     PROCESS_INFORMATION rProcInfo;
  100.  
  101.     ASSERT(lpszHelpPath != NULL);
  102.     if (lpszHelpPath == NULL)
  103.         return FALSE;
  104.  
  105.     _tcscpy(szHelpPathEx, _T("file:"));
  106.     _tcscat(szHelpPathEx, lpszHelpPath);
  107.  
  108.     return CreateProcess(_T("PegHelp.exe"), (LPWSTR)szHelpPathEx,
  109.                NULL, NULL, FALSE, 0, NULL, NULL, NULL, &rProcInfo);
  110. }
  111.  
  112. void wce_WaitMessage()
  113. {
  114.     MSG msg;
  115.  
  116.     while(!PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
  117.         Sleep(100);
  118. }
  119.  
  120. // Note: we aren't handling variable arguments in this workaround.  The only 
  121. // call we're servicing is the one found in afxtrace.cpp
  122. int wce_wsprintfA(LPSTR szBuf, LPCSTR szFormat, UINT nArg)
  123. {
  124.     TCHAR *szwBuf = wce_AsciiToWide(szBuf);
  125.     TCHAR *szwFormat = wce_AsciiToWide(szFormat);
  126.     int nRetVal = 0;
  127.  
  128.     if((szwBuf != NULL) && (szwBuf != szwFormat))
  129.         nRetVal = wsprintf(szwBuf, szwFormat, nArg);
  130.  
  131.     delete [] szwBuf;
  132.     delete [] szwFormat;
  133.     return nRetVal;
  134. }
  135.  
  136. int wce_GetClipboardFormatNameA(UINT format, LPSTR lpszFormatName, int cchMaxCount)
  137. {
  138.     TCHAR *lpwszFormatName = wce_AsciiToWide(lpszFormatName);
  139.     int nRetVal = 0;
  140.  
  141.     if(lpwszFormatName != NULL)
  142.         nRetVal = GetClipboardFormatName(format, lpwszFormatName, cchMaxCount); 
  143.  
  144.     delete [] lpwszFormatName;
  145.     return nRetVal;
  146. }
  147.  
  148. BOOL wce_IsBadStringPtrA(LPCSTR lpsz, UINT ucchMax)
  149. {
  150. // WinCE: our workaround is to check to see if the first character 
  151. // and last character are readable
  152.     if(IsBadReadPtr(lpsz, 1))
  153.         return FALSE;
  154.  
  155.     int nLen = (ucchMax == -1) ? strlen(lpsz) : 
  156.         min((int)ucchMax, strlen(lpsz));
  157.     return ::IsBadReadPtr(lpsz + nLen, 1);
  158. }
  159.  
  160. BOOL wce_IsBadStringPtrW(LPCWSTR lpsz, UINT ucchMax)
  161. {
  162. // WinCE: our workaround is to check to see if the first character 
  163. // and last character are readable
  164.     if(IsBadReadPtr(lpsz, 1))
  165.         return FALSE;
  166.  
  167.     int nLen = (ucchMax == -1) ? wcslen(lpsz) : 
  168.         min((int)ucchMax, wcslen(lpsz));
  169.     return ::IsBadReadPtr(lpsz + nLen, 1);
  170. }
  171.  
  172. #if defined(_WIN32_WCE_EMULATION)
  173. extern "C" DWORD WINAPI GetCurrentDirectoryW(DWORD nBufferLength, LPTSTR lpBuffer); 
  174. BOOL wce_CheckEmulationLibs(HINSTANCE hInstance)
  175. {
  176.     TCHAR szCurrDir[MAX_PATH] = _T("");  
  177.     TCHAR szMsg[256];
  178.     HANDLE hLoadLibraryInstance;
  179.  
  180.     // Is MFC Dll in the emulation directory on the hard disk?
  181.     if(!::GetModuleFileName(hInstance, szCurrDir, _MAX_PATH))
  182.     {    
  183.         VERIFY(::GetCurrentDirectoryW(MAX_PATH, szCurrDir));  // NOTE: Previously set by emulation's COREDLL.DLL.
  184.         _stprintf(szMsg, _T("Initialization of the MFC application failed.  ")
  185.                           _T("Is the EXE or DLL in the correct emulation directory?\n(e.g. %s)"),
  186.                           szCurrDir);
  187.         ::MessageBox(NULL, szMsg, _T("Error"), MB_ICONEXCLAMATION);
  188.         return FALSE;
  189.     }
  190.  
  191.     // Is the MFC Dll in the emulation directory on the hard disk?
  192.     TCHAR* szSlash = wcsrchr(szCurrDir,'\\');
  193.     if((hLoadLibraryInstance = LoadLibrary((szSlash == NULL)?szCurrDir:szSlash+1)) == NULL)
  194.     {
  195.         _stprintf(szMsg, _T("Initialization of the MFC application failed.  ")
  196.                           _T("The MFC Dll is not in the emulation object store.\n(e.g. %s)"),
  197.                           szCurrDir);
  198.         ::MessageBox(NULL, szMsg, _T("Error"), MB_ICONEXCLAMATION);
  199.         return FALSE;
  200.     }
  201.  
  202.     return TRUE;
  203. }
  204. #endif // _WIN32_WCE_EMULATION
  205.  
  206. void wce_ReportDebugBreak(TCHAR* szFile, int nLine)
  207. {
  208.     TCHAR szBuf[100];
  209.     wsprintf(szBuf,_T("Breakpoint at %s, line %d"),szFile,nLine);
  210.     ::MessageBox(NULL,szBuf,NULL,MB_OK);
  211. }
  212.  
  213. UINT wce_GetMenuItemID(HMENU hMenu, int nPos)
  214. {    
  215.     MENUITEMINFO mii;
  216.     memset((char *)&mii, 0, sizeof(mii));
  217.     mii.cbSize = sizeof(mii); 
  218.     mii.fMask  = MIIM_ID; 
  219.     ::GetMenuItemInfo(hMenu, nPos, TRUE, &mii);
  220.  
  221.     return mii.wID; 
  222. }
  223.  
  224. HMENU wce_GetMenu(HWND hWnd)
  225. {
  226.     CWnd *pWnd = CWnd::FromHandle(hWnd);
  227.     if(pWnd == NULL)
  228.         return NULL;
  229.  
  230.     return pWnd->m_hMenu;
  231. }
  232.  
  233. BOOL wce_SetMenu(HWND hWnd, HMENU hMenu)
  234. {
  235.     CWnd *pWnd = CWnd::FromHandle(hWnd);
  236.     if(pWnd == NULL)
  237.         return FALSE;
  238.  
  239.     pWnd->m_hMenu = hMenu;
  240.     return TRUE;
  241. }
  242.  
  243. UINT wce_GetMenuState(HMENU hMenu, UINT uId, UINT uFlags)
  244. {
  245.     MENUITEMINFO mii;
  246.  
  247.     memset((char *)&mii, 0, sizeof(MENUITEMINFO));
  248.     mii.cbSize = sizeof(MENUITEMINFO);
  249.     mii.fMask  = MIIM_ID;
  250.  
  251.     if (uFlags & MF_BYPOSITION)
  252.         ::GetMenuItemInfo(hMenu, uId, TRUE, &mii);
  253.     else
  254.         ::GetMenuItemInfo(hMenu, uId, FALSE, &mii);
  255.  
  256.     return mii.fState;
  257. }
  258.  
  259. BOOL wce_ModifyMenu(HMENU   hMenu,      // handle of menu 
  260.                      UINT    uPosition,  // menu item to modify 
  261.                      UINT    uFlags,     // menu item flags 
  262.                      UINT    uIDNewItem, // menu item identifier or handle of drop-down menu or submenu 
  263.                      LPCTSTR lpNewItem) // menu item content 
  264. {
  265.     // Handle MF_BYCOMMAND case
  266.     if ((uFlags & MF_BYPOSITION) != MF_BYPOSITION)
  267.     {    
  268.         int nMax = wce_GetMenuItemCount(hMenu);
  269.         int nCount = 0;
  270.         while (uPosition != wce_GetMenuItemID(hMenu, nCount) && (nCount < nMax))
  271.             nCount++;
  272.         ASSERT(nCount < nMax);
  273.         uPosition = nCount;
  274.         uFlags |= MF_BYPOSITION;
  275.     }
  276.  
  277.     if (!::DeleteMenu(hMenu, uPosition, uFlags))
  278.         return FALSE;
  279.  
  280.     return ::InsertMenu(hMenu, uPosition, uFlags, uIDNewItem, lpNewItem);
  281. }
  282.  
  283. int wce_GetMenuItemCount(HMENU hMenu)
  284. {
  285.     const int MAX_NUM_ITEMS = 256;
  286.     int  iPos, iCount;
  287.  
  288.     MENUITEMINFO mii;
  289.     memset((char *)&mii, 0, sizeof(MENUITEMINFO));
  290.     mii.cbSize = sizeof(MENUITEMINFO);
  291.  
  292.     iCount = 0;
  293.     for (iPos = 0; iPos < MAX_NUM_ITEMS; iPos++)
  294.     {
  295.         if(!GetMenuItemInfo(hMenu, (UINT)iPos, TRUE, &mii))
  296.             break;
  297.         iCount++;
  298.     }
  299.  
  300.     return iCount;
  301. }
  302.  
  303. int wce_GetMenuString(HMENU hMenu, UINT uIDItem, LPWSTR lpString, int nMaxCount, UINT uFlag)
  304.     MENUITEMINFO mii;
  305.     memset((char *)&mii, 0, sizeof(MENUITEMINFO));
  306.     mii.cbSize = sizeof(MENUITEMINFO);
  307.  
  308.     if (!GetMenuItemInfo(hMenu, 0, TRUE, &mii))
  309.         return 0;
  310.     
  311.     mii.fMask      = MIIM_TYPE;  // to get dwTypeData
  312.     mii.fType      = MFT_STRING; // to get dwTypeData
  313.     mii.dwTypeData = lpString;
  314.     mii.cch        = nMaxCount;
  315.  
  316.     if (uFlag == MF_BYPOSITION)
  317.         ::GetMenuItemInfo(hMenu, uIDItem, TRUE, &mii);
  318.     else
  319.     {
  320.         ASSERT(uFlag == MF_BYCOMMAND);
  321.         ::GetMenuItemInfo(hMenu, uIDItem, FALSE, &mii);
  322.     }
  323.  
  324.     if (mii.dwTypeData != NULL)
  325.         return _tcslen(lpString);
  326.  
  327.     return 0;
  328. }
  329.  
  330. HPEN wce_CreatePen(int nPenStyle, int nWidth, COLORREF crColor)
  331.     LOGPEN logPen;
  332.     
  333.     if(nPenStyle == PS_DOT)
  334.         nPenStyle = PS_DASH;
  335.     logPen.lopnStyle   = nPenStyle;
  336.     if(nWidth == 0)
  337.         nWidth = 1;
  338.     logPen.lopnWidth.x = nWidth;
  339.     logPen.lopnWidth.y = 1;
  340.     logPen.lopnColor   = crColor;
  341.  
  342.     return ::CreatePenIndirect(&logPen); 
  343. }
  344.  
  345. HBRUSH wce_CreateBrushIndirect(const LOGBRUSH* lplb)
  346. {
  347.     if (lplb->lbStyle == BS_SOLID)
  348.         return ::CreateSolidBrush(lplb->lbColor);
  349.     if (lplb->lbStyle == BS_NULL)    
  350.         return (HBRUSH)::GetStockObject(NULL_BRUSH);
  351.     if (lplb->lbStyle == BS_DIBPATTERNPT)
  352.     {
  353.         ASSERT(lplb->lbColor == DIB_RGB_COLORS);
  354.         return ::CreateDIBPatternBrushPt((void*)lplb->lbHatch, lplb->lbColor);
  355.     }
  356.     TRACE0("LOGBRUSH style member is invalid");
  357.     return NULL;
  358. }
  359.  
  360. HFONT wce_CreateFont(int nHeight, int nWidth, int nEscapement,
  361.         int nOrientation, int nWeight, BYTE bItalic, BYTE bUnderline,
  362.         BYTE cStrikeOut, BYTE nCharSet, BYTE nOutPrecision,
  363.         BYTE nClipPrecision, BYTE nQuality, BYTE nPitchAndFamily,
  364.         LPCTSTR lpszFacename)
  365. {
  366.     LOGFONT logFont;
  367.     logFont.lfHeight = nHeight;
  368.     logFont.lfWidth = nWidth;
  369.     logFont.lfEscapement = nEscapement;
  370.     logFont.lfOrientation = nOrientation;
  371.     logFont.lfWeight = nWeight;
  372.     logFont.lfItalic = bItalic;
  373.     logFont.lfUnderline = bUnderline;
  374.     logFont.lfStrikeOut = cStrikeOut;
  375.     logFont.lfCharSet = nCharSet;
  376.     logFont.lfOutPrecision = nOutPrecision;
  377.     logFont.lfClipPrecision = nClipPrecision;
  378.     logFont.lfQuality = nQuality;
  379.     logFont.lfPitchAndFamily = nPitchAndFamily;
  380.     lstrcpyn(logFont.lfFaceName, lpszFacename, _countof(logFont.lfFaceName));
  381.  
  382.     return ::CreateFontIndirect(&logFont);
  383. }
  384.  
  385. HRGN wce_CreateRectRgn(int x1, int y1, int x2, int y2)
  386. {
  387.     CRect rect(x1,y1,x2,y2);
  388.     return ::CreateRectRgnIndirect(&rect); 
  389. }
  390.  
  391. BOOL wce_SetRectRgn(HRGN hrgn, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect)
  392. {
  393.     BOOL bRetVal = TRUE;
  394.     HRGN hrgnCopy;
  395.     hrgnCopy = ::wce_CreateRectRgn(nLeftRect, nTopRect, nRightRect, nBottomRect); 
  396.     if (hrgnCopy == NULL)
  397.         return FALSE;
  398.     if (::CombineRgn(hrgn, hrgnCopy, NULL, RGN_COPY) == ERROR)
  399.         bRetVal = FALSE;
  400.     ::DeleteObject(hrgnCopy);
  401.     return bRetVal;
  402. }
  403.  
  404. BOOL wce_GetBrushOrgEx(HDC hdc, LPPOINT lppt)
  405. {
  406.     if (::SetBrushOrgEx(hdc, 0, 0, lppt) == FALSE)
  407.         return FALSE;
  408.     return ::SetBrushOrgEx(hdc, lppt->x, lppt->y, NULL);
  409. }
  410.  
  411. int wce_OffsetClipRgn(HDC hdc, int nXOffset, int nYOffset)
  412. {
  413.     int nRetVal;
  414.     HRGN hrgn;
  415.     hrgn = ::wce_CreateRectRgn(0,0,1,1); 
  416.     if (::GetClipRgn(hdc, hrgn) == -1)
  417.         nRetVal = ERROR;
  418.     else
  419.     {
  420.         if (::OffsetRgn(hrgn, nXOffset, nYOffset) == ERROR)
  421.             nRetVal = ERROR;
  422.         else
  423.             nRetVal = ::SelectClipRgn(hdc,hrgn);    
  424.     }
  425.     ::DeleteObject(hrgn);
  426.     return nRetVal;
  427. }
  428.  
  429. int wce_ExtSelectClipRgn(HDC hdc, HRGN hrgn, int fnMode)
  430. {
  431.     ASSERT((hrgn != NULL) || (fnMode == RGN_COPY));
  432.     int nRetVal;
  433.     if (fnMode == RGN_COPY)
  434.         nRetVal = ::SelectClipRgn(hdc, hrgn);    
  435.     else
  436.     {
  437.         HRGN hrgnClip;
  438.         hrgnClip = ::wce_CreateRectRgn(0,0,1,1); 
  439.         if (::GetClipRgn(hdc, hrgnClip) == -1)
  440.             nRetVal = ERROR;
  441.         else 
  442.         {
  443.             if (::CombineRgn(hrgnClip, hrgnClip, hrgn, fnMode) == ERROR)
  444.                 nRetVal = ERROR;
  445.             else 
  446.                 nRetVal = ::SelectClipRgn(hdc, hrgnClip);
  447.         }
  448.         ::DeleteObject(hrgnClip);
  449.     }
  450.     return nRetVal;
  451. }
  452.  
  453. int wce_ExcludeUpdateRgn(HDC hDC, HWND hWnd)
  454. {
  455.     int nRetVal;
  456.     HRGN hrgn;
  457.     hrgn = ::wce_CreateRectRgn(0,0,1,1); 
  458.     nRetVal = ::GetUpdateRgn(hWnd, hrgn, FALSE);
  459.     if (nRetVal != ERROR)
  460.     {
  461.         if (::wce_ExtSelectClipRgn(hDC, hrgn, RGN_DIFF) == ERROR)
  462.             nRetVal = ERROR;
  463.     }
  464.     ::DeleteObject(hrgn);
  465.     return nRetVal;
  466. }
  467.  
  468. BOOL wce_PolyPolyline(HDC hdc, const POINT* lppt, const DWORD* lpdwPolyPoints, DWORD cCount)
  469. {
  470.     if (cCount < 0)
  471.         return FALSE;
  472.     BOOL bResult = TRUE;
  473.     int startIndex = 0;
  474.     for (DWORD i=0; i < cCount && bResult; i++) 
  475.     {
  476.         ASSERT(lpdwPolyPoints[i] >= 2);
  477.         bResult = ::Polyline(hdc, &(lppt[startIndex]), lpdwPolyPoints[i]);
  478.         startIndex += lpdwPolyPoints[i]; // jump to next polyline
  479.     }
  480.     return bResult;
  481. }
  482.  
  483. BOOL wce_PolyPolygon(HDC hdc, const POINT* lpPoints, const int* lpPolyCounts, int nCount)
  484. {
  485.     if (nCount < 2)
  486.         return FALSE;
  487.     BOOL bResult = TRUE;
  488.     int startIndex = 0;
  489.     for (int i=0; i < nCount && bResult; i++) 
  490.     {
  491.         ASSERT(lpPolyCounts[i] >= 2);
  492.         bResult = ::Polygon(hdc, &(lpPoints[startIndex]), lpPolyCounts[i]);
  493.         startIndex += lpPolyCounts[i]; // jump to next polygon
  494.     }
  495.     return bResult;
  496. }
  497.  
  498. int wce_FrameRect(HDC hdc, const RECT* lprc, HBRUSH hbr)
  499. {
  500.     // Fill a "line-size" rectangle for each edge of the frame, using hbr
  501.     // Note that right/bottom borders not painted by FillRect (or FrameRect)
  502.     RECT rectEdge;    
  503.     if (::SetRect(&rectEdge, lprc->left, lprc->top, lprc->right, 
  504.                   lprc->top + 1) == FALSE) // Top edge of frame
  505.         return FALSE;
  506.     if (::FillRect(hdc, &rectEdge, hbr) == FALSE)
  507.         return FALSE;
  508.     
  509.     if (::SetRect(&rectEdge, lprc->right - 1, lprc->top, lprc->right, 
  510.                   lprc->bottom) == FALSE) // Right edge of frame
  511.         return FALSE;
  512.     if (::FillRect(hdc, &rectEdge, hbr) == FALSE)
  513.         return FALSE;
  514.     if (::SetRect(&rectEdge, lprc->left, lprc->bottom - 1, lprc->right, 
  515.                   lprc->bottom) == FALSE) // Bottom edge of frame
  516.         return FALSE;
  517.     if (::FillRect(hdc, &rectEdge, hbr) == FALSE)
  518.         return FALSE;
  519.     if (::SetRect(&rectEdge, lprc->left, lprc->top, lprc->left + 1, 
  520.                   lprc->bottom) == FALSE) // Left edge of frame
  521.         return FALSE;
  522.     return ::FillRect(hdc, &rectEdge, hbr);
  523. }
  524.  
  525. LONG wce_RegCreateKey(HKEY hKey, LPCWSTR lpSubKey, PHKEY phkResult)
  526. {
  527.     long lResult = 0;
  528.     DWORD dwDisposition = 0;
  529.  
  530.     lResult = RegCreateKeyExW(hKey, lpSubKey, 0, NULL, NULL, KEY_ALL_ACCESS, NULL, 
  531.                               phkResult, &dwDisposition);
  532.     return lResult;
  533. }
  534.  
  535. LONG wce_RegQueryValue(HKEY hKey, LPCWSTR lpRegValue, LPWSTR lpValue, PLONG lpcbValue)
  536. {
  537.     long  lResult     = 0;
  538.     DWORD dwValueType = 0;
  539.  
  540.     lResult = RegQueryValueExW((HKEY)hKey, (LPTSTR)lpRegValue, (LPDWORD)NULL, 
  541.         (LPDWORD)&dwValueType, (LPBYTE)lpValue, (LPDWORD)lpcbValue);
  542.     return lResult;
  543. }
  544.  
  545. LONG wce_RegOpenKey(HKEY     hKey,            // handle of open key 
  546.                      LPCTSTR  lpSubKey,        // address of name of subkey to open 
  547.                      PHKEY  phkResult)     // address of handle of open key 
  548. {
  549.     long lResult = 0;
  550.     HANDLE hBuffer = NULL;
  551.  
  552.     lResult = RegOpenKeyExW(hKey, lpSubKey, 0, KEY_ALL_ACCESS, phkResult);
  553.     if(lResult == ERROR_SUCCESS)
  554.         return lResult;
  555.  
  556.     // Workaround:  the KEY_ALL_ACCESS above contains KEY_CREATE_SUB_KEY, except
  557.     // that it's not supported in WinCE.  So if an error results, check to see if its
  558.     // a value that's meant to be converted to a key (which is the behavior of the 
  559.     // desktop RegOpenKey()).
  560.  
  561.     BYTE *lpBuffer;
  562.     DWORD dwType;
  563.     DWORD dwSize;
  564.     long lPrevResult = lResult;
  565.     
  566.     lResult = RegQueryValueEx(hKey, lpSubKey, 0, &dwType, NULL, &dwSize);
  567.     if(lResult != ERROR_SUCCESS)
  568.         return lResult;
  569.  
  570.     ASSERT(dwSize > 0);
  571.     hBuffer = LocalAlloc(LMEM_FIXED, dwSize);
  572.     if(hBuffer == NULL)
  573.         return ERROR_NOT_ENOUGH_MEMORY;
  574.  
  575.     lpBuffer = (BYTE*)WCE_FCTN(GlobalLock)(hBuffer);
  576.     lResult = RegQueryValueEx(hKey, lpSubKey, 0, &dwType, lpBuffer, &dwSize);
  577.     if(lResult != ERROR_SUCCESS)
  578.     {
  579.         lResult = lPrevResult;
  580.         goto wceROK_ERROR;
  581.     }
  582.  
  583.     lResult = RegDeleteValue(hKey, lpSubKey);
  584.     if(lResult != ERROR_SUCCESS)
  585.     {
  586.         lResult = lPrevResult;
  587.         goto wceROK_ERROR;
  588.     }
  589.  
  590.     DWORD dwDisposition;
  591.     lResult = RegCreateKeyEx(hKey, lpSubKey, 0, NULL, NULL, KEY_ALL_ACCESS, NULL, 
  592.                              phkResult, &dwDisposition);
  593.     if(lResult != ERROR_SUCCESS)
  594.     {
  595.         lResult = lPrevResult;
  596.         goto wceROK_ERROR;
  597.     }
  598.  
  599.     lResult = RegSetValueEx(*phkResult, lpSubKey, 0, dwType, lpBuffer, dwSize);
  600.     if(lResult != ERROR_SUCCESS)
  601.     {
  602.         lResult = lPrevResult;
  603.         goto wceROK_ERROR;
  604.     }
  605.  
  606. wceROK_ERROR:
  607.     if(hBuffer != NULL)
  608.     {
  609.         LocalLock(hBuffer);
  610.         LocalFree(hBuffer);
  611.     }
  612.  
  613.     return lResult;
  614.  
  615. }
  616.  
  617. // RegSetValueEx is used as a workaround  for RegSetValue, but is not behaviorally
  618. // equivalent. If the specified key doesn't exist and it's not a value, RegSetValue 
  619. // creates a key, and applies the value to it.  
  620. // RegSetValueEx doesn't do this, it rather creates another value under the specified
  621. // prarent key.  Our override is to detect this circumstance, and creating a key
  622. // manually before calling RegSetValueEx.
  623. // Note: this workaround does not claim to be equivalent to RegSetValue.
  624. LONG wce_RegSetValue(HKEY hKey, LPCTSTR lpSubKey, DWORD dwType, LPCTSTR lpData,  
  625.                      DWORD cbData)
  626. {
  627.     LONG lResult;
  628.     HKEY hSubKey;
  629.  
  630.     // If lpSubKey is NULL or an empty string, just delegate to the Ex function
  631.     if((lpSubKey == NULL) || (*lpSubKey == _T('\0')))
  632.     {
  633.         return RegSetValueEx(hKey, lpSubKey, 0 /*reserved*/, dwType,
  634.             (CONST BYTE*)lpData, (cbData + 1) * sizeof(TCHAR));
  635.     }
  636.  
  637.     // NOTE: in the following, we do not want to pass in KEY_CREATE_SUB_KEY (nevermind the
  638.     // fact that that particular flag isn't supported in WinCE 2.0).  We just want to do a 
  639.     // test and don't want an automatic conversion from a value to a key.
  640.     lResult = RegOpenKeyEx(hKey, lpSubKey, 0, 0, &hSubKey);
  641.     if(lResult != ERROR_SUCCESS) 
  642.     {    // it's not a key, so it's either a value or emptiness. So that means another test. 
  643.         DWORD dwType,dwSize;
  644.         lResult = RegQueryValueEx(hKey, lpSubKey, 0, &dwType, NULL, &dwSize);
  645.         if(lResult == ERROR_SUCCESS) // it's a value
  646.         {
  647.             // We can call RegSetValueEx now because we want to keep it as a value
  648.             return RegSetValueEx(hKey, lpSubKey, 0 /*reserved*/, dwType,
  649.                 (CONST BYTE*)lpData, (cbData + 1) * sizeof(TCHAR));
  650.         }
  651.         else // We have emptiness... create a key
  652.         {
  653.             DWORD dwDisposition;
  654.             lResult = RegCreateKeyEx(hKey, lpSubKey, 0, NULL, NULL, KEY_ALL_ACCESS, NULL, 
  655.                                      &hSubKey, &dwDisposition);
  656.             if(lResult != ERROR_SUCCESS)
  657.                 return lResult;
  658.         }
  659.     }
  660.  
  661.     // At this point, we have a hSubKey.  Set its default value.  
  662.     // This can only be done with strings.
  663.     ASSERT(dwType == REG_SZ);
  664.     return RegSetValueEx(hSubKey, _T(""), 0 /*reserved*/, dwType,
  665.         (CONST BYTE*)lpData, (cbData + 1) * sizeof(TCHAR));
  666. }
  667.  
  668.  
  669. LONG wce_RegEnumKey(HKEY    hKey,        // handle of key to query 
  670.                      DWORD   dwIndex,    // index of subkey to query 
  671.                      LPTSTR  lpName,    // address of buffer for subkey name  
  672.                      DWORD   cbName)    // size of subkey buffer 
  673. {
  674.     long      lResult;
  675.     FILETIME  rFileTime;
  676.  
  677.     lResult = RegEnumKeyExW(hKey, dwIndex, lpName, &cbName, NULL, NULL,
  678.                             NULL, &rFileTime);
  679.     return lResult;
  680. }
  681.  
  682.  
  683. // Returns key for HKEY_CURRENT_USER\"Software"\RegistryKey\ProfileName,
  684. // creating it if it doesn't exist.
  685. // Responsibility of the caller to call RegCloseKey() on the returned HKEY.
  686. // INI strings are not localized.
  687. static const TCHAR szSoftware[]    = _T("\\Software");
  688. static const TCHAR szRegistryKey[] = _T("Microsoft\\MFC_WCE");
  689. static const TCHAR szProfileName[] = _T("afx.ini");
  690. HKEY wce_GetAppRegistryKey()
  691. {
  692.     HKEY hAppKey     = NULL;
  693.     HKEY hSoftKey    = NULL;
  694.     HKEY hCompanyKey = NULL;
  695.     long lResult     = 0;
  696.  
  697.     if (RegOpenKeyEx(HKEY_CURRENT_USER, szSoftware, 0, KEY_ALL_ACCESS, &hSoftKey) == ERROR_SUCCESS)
  698.     {
  699.         DWORD dw;
  700.         if (RegCreateKeyEx(hSoftKey, szRegistryKey, 0, REG_NONE, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
  701.             &hCompanyKey, &dw) == ERROR_SUCCESS)
  702.         {
  703.             long lResult = RegCreateKeyEx(hCompanyKey, szProfileName, 0, REG_NONE, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
  704.                 &hAppKey, &dw);
  705.             ASSERT(lResult == ERROR_SUCCESS);
  706.         }
  707.         else
  708.             ASSERT(FALSE);
  709.     }
  710.     if (hSoftKey != NULL)
  711.     {
  712.         lResult = RegCloseKey(hSoftKey);
  713.         ASSERT(lResult == ERROR_SUCCESS);
  714.     }
  715.     if (hCompanyKey != NULL)
  716.     {
  717.         lResult = RegCloseKey(hCompanyKey);
  718.         ASSERT(lResult == ERROR_SUCCESS);
  719.     }
  720.  
  721.     return hAppKey;
  722. }
  723.  
  724.  
  725. // Returns key for:
  726. //      HKEY_CURRENT_USER\"Software"\RegistryKey\AppName\lpszSection
  727. // creating it if it doesn't exist.
  728. // Responsibility of the caller to call RegCloseKey() on the returned HKEY.
  729. HKEY wce_GetSectionKey(LPCTSTR lpszSection)
  730. {
  731.     long lResult = 0;
  732.  
  733.     ASSERT(lpszSection != NULL);
  734.  
  735.     HKEY hSectionKey = NULL;
  736.     HKEY hAppKey = wce_GetAppRegistryKey();
  737.     if (hAppKey == NULL)
  738.         return NULL;
  739.  
  740.     DWORD dw;
  741.     lResult = RegCreateKeyEx(hAppKey, lpszSection, 0, REG_NONE,
  742.         REG_OPTION_NON_VOLATILE, KEY_WRITE|KEY_READ, NULL,
  743.         &hSectionKey, &dw);
  744.     ASSERT(lResult == ERROR_SUCCESS);
  745.  
  746.     lResult = RegCloseKey(hAppKey);
  747.     ASSERT(lResult == ERROR_SUCCESS);
  748.  
  749.     return hSectionKey;
  750. }
  751.  
  752.  
  753.  
  754. UINT wce_GetSystemDirectory(LPWSTR lpBuffer, UINT uSize)
  755.     wcscpy(lpBuffer, _T("\\WINDOWS")); 
  756.     return (UINT)wcslen(lpBuffer); 
  757. }
  758.  
  759. UINT wce_GetSystemDirectoryA(LPSTR lpBuffer, UINT uSize)
  760. {
  761.         strcpy(lpBuffer,    "\\WINDOWS" );
  762.         return (UINT)strlen(lpBuffer);
  763. }
  764.  
  765. TCHAR* wce_GetNextArg(TCHAR* pszArgList, TCHAR szArg[])
  766. {
  767.  
  768.     TCHAR*  pszSpace     = NULL;
  769.     TCHAR*  pszTab       = NULL;
  770.     TCHAR*  pszNextArg   = NULL;
  771.     LPTSTR  pszArg       = &szArg[0];
  772.     int     iWhiteCount  = 0;
  773.  
  774.     if ((pszArgList == NULL) || (lstrlen(pszArgList) == 0))
  775.         return NULL;
  776.  
  777.     // count white space
  778.     iWhiteCount = 0;
  779.     pszSpace    = &pszArgList[0];
  780.     while ((*pszSpace++ == (short)' ') || (*pszSpace++ == (short)'\t'))
  781.         iWhiteCount++;
  782.  
  783.     // copy next arg to szArg
  784.     lstrcpy(szArg, &pszArgList[iWhiteCount]);
  785.     pszArg = &szArg[0];
  786.  
  787.     // null-terminate it
  788.     // point pszNextArg at next arg
  789.     pszSpace = _tcschr(szArg, (int)' ');
  790.     pszTab   = _tcschr(szArg, (int)'\t');
  791.     if ((pszSpace == NULL) && (pszTab != NULL))
  792.     {
  793.         pszSpace = pszTab;
  794.     }
  795.     else if ((pszSpace != NULL) && (pszTab != NULL))
  796.     {
  797.         if (pszTab < pszSpace)
  798.             pszSpace = pszTab;
  799.     }
  800.     if (pszSpace)
  801.     {
  802.         *pszSpace = 0;
  803.         pszNextArg = pszSpace + 1;
  804.     }
  805.     else
  806.         pszNextArg = &szArg[lstrlen(szArg)+1];
  807.  
  808.     ASSERT(pszArg != NULL);
  809.  
  810.     // return pointer to beginning of next arg in list
  811.     return pszNextArg;
  812. }
  813.  
  814.  
  815. int wce_GetArgCount(TCHAR* pszArgList)
  816. {
  817.  
  818.     TCHAR*  pszSpace     = NULL;
  819.     TCHAR*  pszTab       = NULL;
  820.     TCHAR*  pszNextArg   = NULL;
  821.     int     iWhiteCount  = 0;
  822.     int     iArgCount    = 0;
  823.  
  824.     if ((pszArgList == NULL) || (lstrlen(pszArgList) == 0))
  825.         return 0;
  826.  
  827.     iArgCount  = 0;
  828.     pszNextArg = pszArgList;
  829.     while (pszNextArg != NULL)
  830.     {
  831.         // gobble/count white space
  832.         iWhiteCount = 0;
  833.         pszSpace    = pszNextArg;
  834.         while ((*pszSpace++ == (short)' ') || (*pszSpace++ == (short)'\t'))
  835.             iWhiteCount++;
  836.         // point pszNextArg past the white space
  837.         pszNextArg = &pszNextArg[iWhiteCount];
  838.         // if its not null, then increment the count
  839.         if (pszNextArg != NULL)
  840.             iArgCount++;
  841.         // for next iteration, point pszNextArg at next arg
  842.         pszSpace = _tcschr(pszNextArg, (int)' ');
  843.         pszTab   = _tcschr(pszNextArg, (int)'\t');
  844.         if ((pszSpace == NULL) && (pszTab != NULL))
  845.         {
  846.             pszSpace = pszTab;
  847.         }
  848.         else if ((pszSpace != NULL) && (pszTab != NULL))
  849.         {
  850.             if (pszTab < pszSpace)
  851.                 pszSpace = pszTab;
  852.         }
  853.         if (pszSpace)
  854.             pszNextArg = pszSpace + 1;
  855.         else
  856.             break;  // i.e. we're done
  857.     }
  858.  
  859.     return iArgCount;
  860. }
  861.  
  862. BOOL wce_ArgvW(int argc, char* argv[])
  863. {
  864.     TCHAR szTmp[MAX_PATH*2] = _T("");
  865.  
  866.     if (!argv)
  867.         return TRUE;
  868.  
  869.     for (int i = 0; i < argc; i++)
  870.     {
  871.         if (argv[i])
  872.         {
  873.             // Convert the char* to wchar_t*.
  874.             wce_AsciiToWide(szTmp, argv[i]);
  875.             // Free the previous pointer.
  876.             free(argv[i]);
  877.             // Reset argv[i] to point at the wchar_t*.
  878.             argv[i] = (char*)_tcsdup(szTmp);
  879.             ASSERT(argv[i] != NULL);
  880.             if (!argv[i])
  881.                 return FALSE;
  882.         }
  883.     }
  884.  
  885.     return TRUE;
  886. }
  887.  
  888. DWORD wce_GetObjectStoreFreeSpace()
  889.     STORE_INFORMATION stinfo;
  890.     
  891.     if (GetStoreInformation(&stinfo))
  892.         return stinfo.dwFreeSize;
  893.  
  894.     return 0;
  895. }
  896.  
  897. short wce_GetFileTitleW(LPCTSTR lpszFile,    // pointer to full path and filename for file
  898.                          LPTSTR  lpszTitle,   // pointer to buffer that receives filename
  899.                          WORD cbBuf)         // length of buffer
  900. {
  901.     TCHAR* pszSlashPlus1     = 0;
  902.     int    iLen              = 0;
  903.  
  904.     if ((lpszFile == NULL) || (_tcslen(lpszFile)==0))
  905.         return -1;
  906.  
  907.     // Find last backslash (if present).
  908.     // Point at first char after last backslash.
  909.     pszSlashPlus1 = _tcsrchr(lpszFile, (int)'\\');
  910.     if (pszSlashPlus1 == NULL)
  911.         pszSlashPlus1 = (TCHAR*)lpszFile;
  912.     else
  913.         pszSlashPlus1 = pszSlashPlus1 + 1;
  914.  
  915.     // Compute the length of new string and compare with cbBuf.
  916.     iLen = _tcslen(pszSlashPlus1);
  917.     if (iLen > (int)cbBuf)
  918.         return -1;
  919.  
  920.     // Copy basename to lpszTitle.
  921.     _tcscpy(lpszTitle, pszSlashPlus1);
  922.  
  923.     return 0;
  924. }
  925.  
  926.  
  927. UINT wce_GetTempFileName(LPCTSTR lpszPathName,       // address of directory name for temporary file
  928.                           LPCTSTR lpszPrefixString,   // address of filename prefix
  929.                           UINT      uUnique,              // dummy
  930.                           LPTSTR  lpszTempFileName)  // address of buffer that receives the new filename
  931. {
  932.     TCHAR szPathNameCopy[_MAX_PATH] = _T("");
  933.  
  934.     uUnique = uUnique;
  935.  
  936.     // Remove trailing backslash.
  937.     // NOTE: Make copy of lpszPathName (since we may need to modify it).
  938.     _tcscpy(szPathNameCopy, lpszPathName);
  939.     int iLen = _tcslen(szPathNameCopy);
  940.     if (szPathNameCopy[iLen-1] == _T('\\'))
  941.         szPathNameCopy[iLen-1] = _T('\0');
  942.  
  943.     // Check for duplicates. If a file with the resulting filename exists, the number is 
  944.     // increased by one and the test for existence is repeated. Testing continues until a 
  945.     // unique filename is found.
  946.     
  947.     CFileStatus status;
  948.     time_t lnSecsSuffix = wce_time(NULL) & 0x000FFFFF;
  949.  
  950.     do {
  951.         wsprintf(lpszTempFileName, _T("%s\\%s%5X.tmp"), szPathNameCopy, lpszPrefixString, 
  952.                    lnSecsSuffix);
  953.         ++lnSecsSuffix;
  954.     } while (CFile::GetStatus(lpszTempFileName, status));
  955.         
  956.     lnSecsSuffix--;
  957.     return (UINT)lnSecsSuffix;
  958. }
  959.  
  960.  
  961. DWORD wce_GetFullPathName(LPCTSTR lpFileName, DWORD nBufferLength, LPWSTR lpBuffer, LPWSTR* lppFilePart)
  962. {
  963.     ASSERT(AfxIsValidString(lpFileName));
  964.     ASSERT(lppFilePart != NULL);
  965.  
  966.     int nLen = _tcslen(lpFileName);
  967.     ASSERT(AfxIsValidAddress(lpBuffer, nLen, TRUE));
  968.     _tcscpy(lpBuffer, lpFileName);
  969.  
  970.     LPTSTR lpszSlash = _tcsrchr(lpBuffer, (int)'\\');
  971.     if (lpszSlash == NULL)
  972.         *lppFilePart = lpBuffer;
  973.     else
  974.         *lppFilePart = lpszSlash+1;
  975.  
  976.     return (DWORD)nLen;
  977. }
  978.  
  979. BOOL wce_GetScrollRange(HWND hWnd, int nBar, LPINT lpMinPos, LPINT lpMaxPos)
  980.     SCROLLINFO si;
  981.  
  982.     memset( &si, 0, sizeof(SCROLLINFO) );
  983.     si.cbSize = sizeof(SCROLLINFO);
  984.     si.fMask  = SIF_RANGE;
  985.  
  986.     if(!GetScrollInfo( hWnd, nBar, &si))
  987.         return (FALSE);
  988.  
  989.     *lpMinPos = si.nMin;
  990.     *lpMaxPos = si.nMax;
  991.  
  992.     return TRUE; 
  993. }
  994.  
  995. int wce_GetScrollPos( HWND hWnd, int nBar)
  996.     BOOL       bIsOK = FALSE;
  997.     SCROLLINFO si;
  998.  
  999.     memset(&si, 0, sizeof(SCROLLINFO));
  1000.     si.cbSize = sizeof(SCROLLINFO);
  1001.     si.fMask  = SIF_POS;
  1002.  
  1003.     if(!GetScrollInfo(hWnd, nBar, &si))
  1004.         return 0;
  1005.  
  1006.     return si.nPos; 
  1007. }
  1008.  
  1009. void wce_ScrollChildren(HWND hWnd, int cx, int cy)
  1010. {
  1011.     // WinCE does not perform any scrolling if the window is
  1012.     // not visible.  This leaves child windows unscrolled.
  1013.     // To account for this oversight, the child windows are moved
  1014.     // directly instead.
  1015.     HWND hWndChild = ::GetWindow(hWnd, GW_CHILD);
  1016.     if (hWndChild != NULL)
  1017.     {
  1018.         for (; hWndChild != NULL;
  1019.             hWndChild = ::wce_GetNextWindow(hWndChild, GW_HWNDNEXT))
  1020.         {
  1021.             RECT rect;
  1022.             ::GetWindowRect(hWndChild, &rect);
  1023.             ::ScreenToClient(hWnd,(POINT*)&rect.left);
  1024.             ::SetWindowPos(hWndChild, NULL,    rect.left-cx, rect.top-cy,
  1025.                 0, 0, SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOZORDER);
  1026.         }
  1027.     }
  1028. }
  1029.  
  1030.  
  1031. // Added the following workaround for InvalidateRgn.
  1032. BOOL wce_InvalidateRgn(HWND hWnd, HRGN hRgn, BOOL bErase)
  1033. {
  1034.     BOOL bReturn;
  1035.     HDC hdc = ::GetDC(hWnd);
  1036.     if(hdc == NULL) // if no DC, just erase the whole thing
  1037.         bReturn = ::InvalidateRect(hWnd,NULL,bErase);
  1038.     else
  1039.     {
  1040.         // Using the DC, get the smallest rectangle that encloses the region.
  1041.         RECT rect;
  1042.         SelectObject(hdc,hRgn);
  1043.         ::GetClipBox(hdc,&rect);
  1044.         bReturn = ::InvalidateRect(hWnd,&rect,bErase);
  1045.         ::ReleaseDC(hWnd,hdc);
  1046.     }
  1047.  
  1048.     return bReturn;
  1049. }
  1050.  
  1051. BOOL wce_EnumChildWindows( HWND hWndParent, WNDENUMPROC lpEnumFunc, LPARAM lParam )
  1052. {
  1053.     if (hWndParent == NULL)
  1054.             return (FALSE);
  1055.  
  1056.     HWND hWndChild = ::GetWindow( hWndParent, GW_CHILD );
  1057.     for (; hWndChild != NULL; hWndChild = ::wce_GetNextWindow(hWndChild, GW_HWNDNEXT))
  1058.     {
  1059.         lpEnumFunc( hWndChild, lParam );
  1060.         wce_EnumChildWindows( hWndChild, lpEnumFunc, lParam );
  1061.     }
  1062.  
  1063.     return (TRUE);
  1064. }
  1065.  
  1066. BOOL wce_RedrawWindow(HWND hWnd, CONST RECT *prcUpdate, HRGN hrgnUpdate, UINT afuRedraw)
  1067. {
  1068.     ::InvalidateRect(hWnd, prcUpdate, afuRedraw & RDW_ERASE ? TRUE : FALSE);
  1069.     if ((afuRedraw & RDW_ERASENOW) || (afuRedraw & RDW_UPDATENOW)) 
  1070.         ::UpdateWindow(hWnd);
  1071.     return TRUE;
  1072. }
  1073.  
  1074. BOOL wce_ShowScrollBar(HWND hWnd, int nBar, BOOL bShow)
  1075. {
  1076. // WinCE: this workaround doesn't work with x86em
  1077. #if defined(_WIN32_WCE_EMULATION)
  1078.     return TRUE;
  1079. #else // _WIN32_WCE_EMULATION
  1080.     DWORD dwStyle = ::GetWindowLong(hWnd, GWL_STYLE);
  1081.     if(bShow)
  1082.         dwStyle |= ((nBar == SB_HORZ) ? WS_HSCROLL : WS_VSCROLL);
  1083.     else
  1084.         dwStyle &= ~((nBar == SB_HORZ) ? WS_HSCROLL : WS_VSCROLL);
  1085.     return (::SetWindowLong(hWnd, GWL_STYLE, dwStyle) != 0);
  1086. #endif // _WIN32_WCE_EMULATION
  1087.     return TRUE;
  1088. }
  1089.  
  1090. int wce_GetSystemMetrics(int nIndex)
  1091. {
  1092.     if(nIndex == SM_DBCSENABLED)
  1093.         return TRUE;
  1094.     else
  1095.         return GetSystemMetrics(nIndex);
  1096. }
  1097.  
  1098. void wce_SendWM_CREATEToDialog(HWND hWnd)
  1099. {
  1100.     CREATESTRUCT cs; // We "recreate" this by doing detective work.
  1101.     TCHAR szDummy[2];
  1102.  
  1103.     int nLen = GetWindowText(hWnd, szDummy, 1); // query len
  1104.     cs.lpszName = new TCHAR[nLen+1];            // create buffer
  1105.     if(cs.lpszName == NULL)
  1106.         return; // If this fails, forget it.
  1107.     GetWindowText(hWnd, (TCHAR*)cs.lpszName, nLen); // un-const cast
  1108.  
  1109.     cs.lpszClass  = new TCHAR[64];
  1110.     GetClassName(hWnd, (TCHAR*)cs.lpszClass, 64);
  1111.  
  1112.     cs.style = GetWindowLong(hWnd, GWL_STYLE);
  1113.     cs.dwExStyle = GetWindowLong(hWnd, GWL_EXSTYLE);
  1114.  
  1115.     cs.hwndParent = GetParent(hWnd);
  1116.     cs.hInstance = AfxGetInstanceHandle();
  1117.  
  1118.     RECT rectDlg;
  1119.     GetWindowRect(hWnd, &rectDlg);
  1120.     if(cs.hwndParent != NULL) // child window?
  1121.     {
  1122.         RECT rectParent;
  1123.         GetWindowRect(cs.hwndParent, &rectParent);
  1124.         OffsetRect(&rectDlg,-rectParent.left,-rectParent.right);
  1125.     }
  1126.     cs.x = rectDlg.left;
  1127.     cs.y = rectDlg.top;
  1128.     cs.cx = rectDlg.right-rectDlg.left;
  1129.     cs.cy = rectDlg.bottom-rectDlg.top;
  1130.     
  1131.     cs.hMenu = NULL;
  1132.     cs.lpCreateParams = 0; // We lost the real lParam when WM_CREATE got eaten by WinCE
  1133.  
  1134.     SendMessage(hWnd,WM_CREATE,0,(LPARAM)&cs);
  1135.  
  1136.     delete[] (TCHAR*)cs.lpszName;
  1137.     delete[] (TCHAR*)cs.lpszClass;
  1138. }
  1139.  
  1140. BOOL CALLBACK wce_FirstDlgProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
  1141. {
  1142.     // This gets called only once--on the first message sent to the dialog window.
  1143.  
  1144.     // We don't own the dlgproc for property sheet, so we have to use the first message
  1145.     // for the first property page as our CBT Hook opportunity.  We fake the
  1146.     // missed WM_INITDIALOG hook.  MFC *will* handle this in dlgprop.cpp (a subset of
  1147.     // the original OnInitDialog implemention) and won't delegate back to the real
  1148.     // dlgproc for the property sheet (if it did, it'd be processing WM_INITDIALOG for
  1149.     // the second time.)
  1150.     _AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
  1151.     CWnd *pWnd = pThreadState->m_pWndInit;
  1152.     if(pThreadState->m_pWndInitPropertySheet != NULL)
  1153.     {
  1154.         HWND hWndPropertySheet = ::GetParent(hWnd);
  1155.         ASSERT(hWndPropertySheet != NULL);
  1156.         ASSERT(pThreadState->m_pWndInit != NULL);
  1157.  
  1158.         CWnd *pWndInitFirstPropPage = pThreadState->m_pWndInit;
  1159.         pThreadState->m_pWndInit    = pThreadState->m_pWndInitPropertySheet;
  1160.         _AfxCbtFilterHook(HCBT_CREATEWND, (WPARAM)hWndPropertySheet, NULL);
  1161.         pThreadState->m_pWndInit    = pWndInitFirstPropPage;
  1162.  
  1163.         ((CPropertySheet*)pThreadState->m_pWndInitPropertySheet)->OnInitDialog();
  1164.         pThreadState->m_pWndInitPropertySheet = NULL;
  1165.     }
  1166.  
  1167.     // Make sure the standard dialog box loop is the OS-owned one
  1168.     ::SetWindowLong(hWnd,GWL_WNDPROC,(LONG)::DefDlgProc);
  1169.  
  1170.     // Let MFC subclass the dialog procedure.
  1171.     if(!pWnd->IsKindOf(RUNTIME_CLASS(CCommonDialog)))
  1172.     {
  1173.         // Common dialogs have OS-owned dialog procedures.  That's why 
  1174.         // MFC hooks with _AfxCommDlgProc. We don't want this relationship broken.
  1175.         ::SetWindowLong(hWnd,DWL_DLGPROC,(LONG)AfxDlgProc); 
  1176.     }
  1177.     
  1178.     // Do normal WNDPROC subclassing now.  Note: after this call, m_pWndInit will
  1179.     // be NULL.  This is important in avoiding reentrancy via _AfxCommDlgProc.
  1180.     _AfxCbtFilterHook(HCBT_CREATEWND,(WPARAM)hWnd,NULL);
  1181.  
  1182.     // Delegate this message to the new subclassed WndProc
  1183.     WNDPROC afxWndProc = AfxGetAfxWndProc();
  1184.  
  1185.     // A nuance of WinCE: WM_CREATE on dialog boxes don't make it to the dialog procedure.
  1186.     // MFC depends on this on at least one count: the CFormView (which is a dialog) wants
  1187.     // to have its OnCreate() called.  Since we're at the actual first message, now 
  1188.     // is the best time to fake the WM_CREATE.  
  1189.     if( (pWnd != NULL) && (pWnd->IsKindOf(RUNTIME_CLASS( CFormView ) ) ) )
  1190.         wce_SendWM_CREATEToDialog(hWnd);
  1191.  
  1192.     // Repump the message through the entire chain.
  1193.     return afxWndProc(hWnd,nMsg,wParam,lParam);
  1194. };
  1195.  
  1196. #define WCE_CLASS_PREFIX _T("WCE_")
  1197.  
  1198. // Register a "hybrid" class (from the current one), substituting a new
  1199. // ClassName and WndProc.  This ensures that the first message is sent
  1200. // to wce_FirstDefWindowProc.
  1201. // NOTE: It is okay to "own" the ThreadState here because the baseline does 
  1202. //       something similar in AfxHookWindowCreate() with pThreadState->m_pWndInit.
  1203. BOOL wce_PreCreateWindow( CREATESTRUCT& cs)
  1204. {
  1205.     // Standalone menus are not supported in ::CreateWindowEx, so we need to filter it out.
  1206.     // We'll cache it later in wce_PostCreateWindow.
  1207.     if(HIWORD(cs.hMenu) != NULL)  // if it is a control ID, then its HIWORD == NULL
  1208.         cs.hMenu = NULL;
  1209.  
  1210.     _AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
  1211.  
  1212.     // Get the old class.  If it doesn't exist, then return FALSE.
  1213.     WNDCLASS wndclass;
  1214.     if (!GetClassInfo( cs.hInstance, cs.lpszClass, &wndclass))
  1215.         return FALSE;
  1216.  
  1217.     // Don't do anything with classes that begin with "Afx."  The 
  1218.     // wce_FirstDefWindowProc is already set for those in 
  1219.     // AfxRegisterClass() and AfxEndDeferRegisterClass()
  1220.     if(_tcsnicmp(cs.lpszClass,_T("Afx"),3) == 0)
  1221.     {
  1222.         pThreadState->m_pOldProc = ::DefWindowProc;
  1223.         // We leave cs.lpszClass alone
  1224.         return TRUE; // don't do anything on MFC windows
  1225.     }
  1226.  
  1227.     // Compose a new class name (e.g. "WCE_oldname"). We account for both
  1228.     // ways new might fail (exceptions vs. NULL ptr)
  1229.     TRY 
  1230.     {
  1231.         wndclass.lpszClassName = new TCHAR[_tcslen(cs.lpszClass) + 
  1232.                                            _tcslen(WCE_CLASS_PREFIX) + 1];
  1233.     } 
  1234.     CATCH_ALL(e) 
  1235.     {
  1236.         return FALSE;
  1237.     } END_CATCH_ALL
  1238.  
  1239.     if(wndclass.lpszClassName == NULL)
  1240.         return FALSE;
  1241.  
  1242.     _tcscpy( (TCHAR*)wndclass.lpszClassName, WCE_CLASS_PREFIX );
  1243.     _tcscat( (TCHAR*)wndclass.lpszClassName, cs.lpszClass );
  1244.                                                                               
  1245.     // Change the window procedure, saving the old one.
  1246.     WNDPROC OldProc      = wndclass.lpfnWndProc;
  1247.     wndclass.lpfnWndProc = (WNDPROC)wce_FirstDefWindowProc;
  1248.  
  1249.     // Register the new class (if not already registered)
  1250.     if (!AfxRegisterClass(&wndclass))
  1251.     {
  1252.         delete[] (void*)wndclass.lpszClassName;
  1253.         return FALSE;
  1254.     }
  1255.  
  1256.     // If successful, commit our change to pThreadState and cs.
  1257.     pThreadState->m_pOldProc = OldProc;
  1258.     cs.lpszClass = wndclass.lpszClassName;
  1259.  
  1260.     // Note: cs.lpszClass will be deleted in wce_PostCreateWindow
  1261.     return TRUE;
  1262. }
  1263.  
  1264.  
  1265.  
  1266. LRESULT CALLBACK wce_FirstDefWindowProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
  1267. {
  1268.     // This gets called only once.  We first plug in the normal DefWindowProc (because
  1269.     // The hook will add it to the chain after plugging in AfxWndProc.)  And then we
  1270.     // delegate to AfxWndProc.
  1271.     // Note: it's possible that the ::CreateEx returns without a chance to call this.  That
  1272.     // case is taken care of after CreateEx (does the same thing here minus the message
  1273.     // delegation.)
  1274.  
  1275.     // Retrieve the old WndProc.
  1276.     _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
  1277.     ASSERT(pThreadState);
  1278.  
  1279.     // Retrieve MFC's WndProc
  1280.     WNDPROC afxWndProc = AfxGetAfxWndProc();
  1281.  
  1282.     // Set current WndProc to oldproc.  After the hook function is finished, then oldproc
  1283.     // will be installed as the m_pfnSuper.
  1284.  
  1285.     ASSERT(pThreadState->m_pOldProc != NULL);
  1286.     ::SetWindowLong(hWnd,GWL_WNDPROC,(LONG)pThreadState->m_pOldProc);
  1287.     pThreadState->m_pOldProc = NULL;
  1288.  
  1289.     // Fake the call to _AfxCbtFilterHook
  1290.     _AfxCbtFilterHook( HCBT_CREATEWND, (WPARAM)hWnd, NULL );
  1291.  
  1292.     // Delegate.
  1293.     return afxWndProc(hWnd,nMsg,wParam,lParam);
  1294. }
  1295.  
  1296.  
  1297. void wce_PostCreateWindow( CREATESTRUCT& cs, HWND hWnd, HMENU nIDorHMenu)
  1298. {
  1299.     // Check to see if the hook has been invoked (sometimes we can have no messages
  1300.     // sent right away, which means wce_FirstDefWindowProc hasn't gotten called yet.)
  1301.     _AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
  1302.     if(pThreadState->m_pWndInit != NULL)
  1303.     {
  1304.         if(hWnd != NULL) 
  1305.         {
  1306.             ASSERT(pThreadState->m_pOldProc != NULL);
  1307.             ::SetWindowLong(hWnd,GWL_WNDPROC,(LONG)pThreadState->m_pOldProc);
  1308.             pThreadState->m_pOldProc = NULL;
  1309.             _AfxCbtFilterHook( HCBT_CREATEWND, (WPARAM)hWnd, NULL );
  1310.         }    
  1311.         else
  1312.         {
  1313.             pThreadState->m_pWndInit = NULL;  
  1314.             pThreadState->m_pOldProc = NULL;
  1315.         }
  1316.     }
  1317.  
  1318.     if(_tcsnicmp(cs.lpszClass,WCE_CLASS_PREFIX,4) == 0)
  1319.         delete[] (void*)cs.lpszClass; // from new in wce_PreCreateWindow
  1320.  
  1321.     // Set the menu (wce_SetMenu just caches it away in CWnd)
  1322.     if((hWnd != NULL) && (HIWORD(nIDorHMenu) != NULL))
  1323.         wce_SetMenu(hWnd, nIDorHMenu);
  1324. }
  1325.  
  1326.  
  1327. LRESULT CALLBACK wce_NullWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
  1328. {
  1329.     // This window procedure is here to eat all messages after a window
  1330.     // has been detached.  The reason for this is that the WM_DESTROY
  1331.     // message below is "close" to being the last message, but we treat
  1332.     // it as such.  After that, we no longer have a CWnd->hWnd attachment,
  1333.     // so we use this WNDPROC to eat up any remaining messages.
  1334.     return 0;
  1335. }
  1336.  
  1337.  
  1338.  
  1339.  
  1340. // Workaround: the width of the property sheet is too big (with an error 
  1341. // proportional to the desired width). We correct for this here.
  1342. void wce_AdjustPropertySheetSize(CPropertySheet *pSheet)
  1343. {
  1344.     int nMaxWidth = 0, nMaxHeight = 0;
  1345.  
  1346.     ASSERT(pSheet->m_hWnd != NULL);
  1347.  
  1348.     for (int i = 0; i < pSheet->GetPageCount(); i++)
  1349.     {
  1350.         const DLGTEMPLATE* pTemplate;
  1351.         CPropertyPage* pPage = pSheet->GetPage(i);
  1352.         CSize size;
  1353.  
  1354.         if (pPage->m_psp.dwFlags & PSP_DLGINDIRECT)
  1355.         {
  1356.             pTemplate = pPage->m_psp.pResource;
  1357.         }
  1358.         else
  1359.         {
  1360.             HRSRC hResource = ::FindResource(pPage->m_psp.hInstance,
  1361.                 pPage->m_psp.pszTemplate, RT_DIALOG);
  1362.             HGLOBAL hTemplate = LoadResource(pPage->m_psp.hInstance,
  1363.                 hResource);
  1364.             pTemplate = (LPCDLGTEMPLATE)LockResource(hTemplate);
  1365.         }
  1366.  
  1367.         CDialogTemplate dlgTemplate(pTemplate);
  1368.         dlgTemplate.GetSizeInPixels(&size);
  1369.         if(size.cx > nMaxWidth)
  1370.             nMaxWidth = size.cx;
  1371.         if(size.cy > nMaxHeight)
  1372.             nMaxHeight = size.cy;
  1373.     }
  1374.  
  1375.  
  1376.     CTabCtrl* pWndTab = (CTabCtrl*)pSheet->GetDlgItem(AFX_IDC_TAB_CONTROL);
  1377.     if(pWndTab != NULL)
  1378.     {
  1379.         CRect rectWndTab, rectWndDlg;
  1380.  
  1381.         pSheet->GetWindowRect(rectWndDlg);
  1382.         pWndTab->GetWindowRect(rectWndTab);
  1383.         int dx = (rectWndTab.left-rectWndDlg.left) + 
  1384.                  (rectWndTab.right-rectWndDlg.right);
  1385.         int dy = (rectWndTab.top-rectWndDlg.top) + 
  1386.                  (rectWndTab.bottom-rectWndDlg.bottom);
  1387.  
  1388.         CRect rectDisplayTab = rectWndTab;
  1389.         pWndTab->AdjustRect(FALSE,&rectDisplayTab);
  1390.         int nButtonHeight = rectDisplayTab.top-rectWndTab.top;
  1391.         int nHSlop = 2;
  1392.         int nVSlop = 12;
  1393.  
  1394.         int nWidth  = nMaxWidth  + 
  1395.             ::GetSystemMetrics(SM_CXEDGE)*2 +
  1396.             ::GetSystemMetrics(SM_CXDLGFRAME)*2 + nHSlop;
  1397.         int nHeight = nMaxHeight + nButtonHeight + nVSlop + 
  1398.             ::GetSystemMetrics(SM_CYEDGE)*2 + 
  1399.             ::GetSystemMetrics(SM_CYDLGFRAME)*2 +
  1400.             ::GetSystemMetrics(SM_CYCAPTION);
  1401.  
  1402.         pSheet->SetWindowPos(NULL, 0, 0, nWidth, nHeight,
  1403.                               SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
  1404.         pWndTab->SetWindowPos(NULL, 0, 0, nWidth - dx, nHeight - dy,
  1405.             SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
  1406.     }
  1407. }
  1408.  
  1409. #if !defined(_WIN32_WCE_NO_WININET)
  1410. BOOL wce_InternetSetOptionEx(HINTERNET hInternet, DWORD dwOption,
  1411.                              LPVOID lpBuffer, DWORD dwBufferLength, DWORD)
  1412. {
  1413.     return InternetSetOption(hInternet, dwOption, lpBuffer, dwBufferLength);
  1414. }
  1415. #endif // _WIN32_WCE_NO_WININET
  1416.  
  1417.