//=--------------------------------------------------------------------------= // CtlHelper.Cpp //=--------------------------------------------------------------------------= // Copyright 1995 Microsoft Corporation. All Rights Reserved. // // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A // PARTICULAR PURPOSE. //=--------------------------------------------------------------------------= // // helper routines for our COleControl implementation // #include "pch.h" #include "CtrlObj.H" #include "CtlHelp.H" #include // for ASSERT and FAIL // SZTHISFILE //=--------------------------------------------------------------------------= // this is used by the window reflection code. // extern BYTE g_fRegisteredReflect; extern const char g_szReflectClassName []; // define this here, since it's the only guid we really need to define in the // framework -- the user control defines all other interesting guids. // static const GUID IID_IControlPrv = { 0xd97180, 0xfcf7, 0x11ce, { 0xa0, 0x9e, 0x0, 0xaa, 0x0, 0x62, 0xbe, 0x57 } }; //=--------------------------------------------------------------------------= // _SpecialKeyState //=--------------------------------------------------------------------------= // returns a short with some information on which of the SHIFT, ALT, and CTRL // keys are set. // // Output: // short - bit 0 is shift, bit 1 is ctrl, bit 2 is ALT. // // Notes: // short _SpecialKeyState() { // don't appear to be able to reduce number of calls to GetKeyState // BOOL bShift = (GetKeyState(VK_SHIFT) < 0); BOOL bCtrl = (GetKeyState(VK_CONTROL) < 0); BOOL bAlt = (GetKeyState(VK_MENU) < 0); return (short)(bShift + (bCtrl << 1) + (bAlt << 2)); } //=--------------------------------------------------------------------------= // CopyOleVerb [helper] //=--------------------------------------------------------------------------= // copies an OLEVERB structure. used in CStandardEnum // // Parameters: // void * - [out] where to copy to // const void * - [in] where to copy from // DWORD - [in] bytes to copy // // Notes: // void WINAPI CopyOleVerb ( void *pvDest, const void *pvSrc, DWORD cbCopy ) { VERBINFO * pVerbDest = (VERBINFO *) pvDest; const VERBINFO * pVerbSrc = (const VERBINFO *) pvSrc; *pVerbDest = *pVerbSrc; ((OLEVERB *)pVerbDest)->lpszVerbName = OLESTRFROMRESID((WORD)((VERBINFO *)pvSrc)->idVerbName); } //=--------------------------------------------------------------------------= // ControlFromUnknown [helper, callable] //=--------------------------------------------------------------------------= // given an unknown, get the COleControl pointer for it. // // Parameters: // IUnknown * - [in] // // Output: // HRESULT // // Notes: // COleControl *ControlFromUnknown ( IUnknown *pUnk ) { HRESULT hr; IControlPrv *pControlPrv = NULL; COleControl *pCtl = NULL; if (!pUnk) return NULL; hr = pUnk->QueryInterface(IID_IControlPrv, (void **)&pControlPrv); ASSERT(SUCCEEDED(hr), "Failed to get IControlPrv interface"); hr = pControlPrv->GetControl(&pCtl); ASSERT(SUCCEEDED(hr), "Failed to get COleControl pointer"); QUICK_RELEASE(pControlPrv); return pCtl; } //=--------------------------------------------------------------------------= // CreateReflectWindow [blech] //=--------------------------------------------------------------------------= // unfortunately, in certain cases, we have to create two windows, one of // which exists strictly to reflect messages on to the control. Majorly // lame. Fortunately, the number of hosts which require this is quite small. // // Parameters: // BOOL - [in] should it be created visible? // HWND - [in] parent window // int - [in] x pos // int - [in] y pos // SIZEL * - [in] size // // Output: // HWND - reflecting hwnd or NULL if it failed. // // Notes: // HWND CreateReflectWindow ( BOOL fVisible, HWND hwndParent, int x, int y, SIZEL *pSize ) { WNDCLASS wndclass; // first thing to do is register the window class. crit sect this // so we don't have to move it into the control // ENTERCRITICALSECTION1(&g_CriticalSection); if (!g_fRegisteredReflect) { memset(&wndclass, 0, sizeof(wndclass)); wndclass.lpfnWndProc = COleControl::ReflectWindowProc; wndclass.hInstance = g_hInstance; wndclass.lpszClassName = g_szReflectClassName; if (!RegisterClass(&wndclass)) { FAIL("Couldn't Register Parking Window Class!"); LEAVECRITICALSECTION1(&g_CriticalSection); return NULL; } g_fRegisteredReflect = TRUE; } LEAVECRITICALSECTION1(&g_CriticalSection); // go and create the window. // return CreateWindowEx(0, g_szReflectClassName, NULL, WS_CHILD | WS_CLIPSIBLINGS |((fVisible) ? WS_VISIBLE : 0), x, y, pSize->cx, pSize->cy, hwndParent, NULL, g_hInstance, NULL); } //=--------------------------------------------------------------------------= // in case the user doesn't want our default window proc, we support // letting them specify one themselves. this is defined in their main ipserver // file. // // Note: As of VB6 we added ParkingWindowProc to the framework. // The ParkingWindowProc supports message reflection which is normally // the code you add to your implementation of ParkingWindowProc. // In most cases you can probably set this to NULL in your control's // implementation // extern WNDPROC g_ParkingWindowProc; //=--------------------------------------------------------------------------= // GetParkingWindow //=--------------------------------------------------------------------------= // creates the global parking window that we'll use to parent things, or // returns the already existing one // // Output: // HWND - our parking window // // Notes: // HWND GetParkingWindow ( void ) { WNDCLASS wndclass; // crit sect this creation for apartment threading support. // ENTERCRITICALSECTION1(&g_CriticalSection); if (g_hwndParking) goto CleanUp; ZeroMemory(&wndclass, sizeof(wndclass)); wndclass.lpfnWndProc = (g_ParkingWindowProc) ? g_ParkingWindowProc : COleControl::ParkingWindowProc; wndclass.hInstance = g_hInstance; wndclass.lpszClassName = "CtlFrameWork_Parking"; if (!RegisterClass(&wndclass)) { FAIL("Couldn't Register Parking Window Class!"); goto CleanUp; } g_hwndParking = CreateWindow("CtlFrameWork_Parking", NULL, WS_POPUP, 0, 0, 0, 0, NULL, NULL, g_hInstance, NULL); ASSERT(g_hwndParking, "Couldn't Create Global parking window!!"); CleanUp: LEAVECRITICALSECTION1(&g_CriticalSection); return g_hwndParking; } //=--------------------------------------------------------------------------= // ParkingWindowProc //=--------------------------------------------------------------------------= // Provides default processing for the parking window. Since your control // may be parented by the parking window, we provide message reflection. // LRESULT CALLBACK COleControl::ParkingWindowProc ( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ) { LRESULT lResult; // If the message is reflected then return the result of the OCM_ message // if (ReflectOcmMessage(hwnd, msg, wParam, lParam, &lResult)) return lResult; return DefWindowProc(hwnd, msg, wParam, lParam); }