HMENU WINAPI __LoadMenuA(HINSTANCE hInstance, LPCSTR lpMenuName) { HMENU hmenu = LoadMenuA(hInstance, lpMenuName); if (lpMenuName == MAKEINTRESOURCEA(IDR_MAIN_MENU)) { InitVDubAuoMenu(hmenu); } return hmenu; }
/* Background menu implementation */ static HRESULT WINAPI BackgroundMenu_QueryContextMenu( IContextMenu3 *iface, HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags) { ContextMenu *This = impl_from_IContextMenu3(iface); HMENU hMyMenu; UINT idMax; HRESULT hr; TRACE("(%p)->(hmenu=%p indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n", This, hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags); hMyMenu = LoadMenuA(shell32_hInstance, "MENU_002"); if (uFlags & CMF_DEFAULTONLY) { HMENU ourMenu = GetSubMenu(hMyMenu,0); UINT oldDef = GetMenuDefaultItem(hMenu,TRUE,GMDI_USEDISABLED); UINT newDef = GetMenuDefaultItem(ourMenu,TRUE,GMDI_USEDISABLED); if (newDef != oldDef) SetMenuDefaultItem(hMenu,newDef,TRUE); if (newDef!=0xFFFFFFFF) hr = MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, newDef+1); else hr = MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0); } else { idMax = Shell_MergeMenus (hMenu, GetSubMenu(hMyMenu,0), indexMenu, idCmdFirst, idCmdLast, MM_SUBMENUSHAVEIDS); hr = MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, idMax-idCmdFirst); } DestroyMenu(hMyMenu); TRACE("(%p)->returning 0x%x\n",This,hr); return hr; }
// Если (anFromShowWindow != -1), значит функу зовут из ShowWindow void OnGuiWindowAttached(HWND hWindow, HMENU hMenu, LPCSTR asClassA, LPCWSTR asClassW, DWORD anStyle, DWORD anStyleEx, BOOL abStyleHidden, int anFromShowWindow/*=-1*/) { DWORD nCurStyle = (DWORD)user->getWindowLongPtrW(hWindow, GWL_STYLE); DWORD nCurStyleEx = (DWORD)user->getWindowLongPtrW(hWindow, GWL_EXSTYLE); user->allowSetForegroundWindow(ASFW_ANY); // VLC создает несколько "подходящих" окон, но ShowWindow зовет // только для одного из них. Поэтому фактический аттач делаем // только в том случае, если окно "видимое" if ((!(nCurStyle & WS_VISIBLE)) && (anFromShowWindow <= SW_HIDE)) { // Значит потом, из ShowWindow return; } ghAttachGuiClient = hWindow; gnAttachGuiClientThreadId = user->getWindowThreadProcessId(hWindow, NULL); gbForceShowGuiClient = TRUE; gbAttachGuiClient = FALSE; // Только одно окно приложения. Пока? #if 0 // Для WS_CHILDWINDOW меню нельзя указать при создании окна if (!hMenu && !ghAttachGuiClientMenu && (asClassA || asClassW)) { BOOL lbRcClass; WNDCLASSEXA wca = {sizeof(WNDCLASSEXA)}; WNDCLASSEXW wcw = {sizeof(WNDCLASSEXW)}; if (asClassA) { lbRcClass = GetClassInfoExA(GetModuleHandle(NULL), asClassA, &wca); if (lbRcClass) ghAttachGuiClientMenu = LoadMenuA(wca.hInstance, wca.lpszMenuName); } else { lbRcClass = GetClassInfoExW(GetModuleHandle(NULL), asClassW, &wcw); if (lbRcClass) ghAttachGuiClientMenu = LoadMenuW(wca.hInstance, wcw.lpszMenuName); } hMenu = ghAttachGuiClientMenu; } if (hMenu) { // Для WS_CHILDWINDOW - не работает SetMenu(hWindow, hMenu); HMENU hSys = GetSystemMenu(hWindow, FALSE); TODO("Это в принципе прокатывает, но нужно транслировать WM_SYSCOMMAND -> WM_COMMAND, соответственно, перехватывать WndProc, или хук ставить"); if (hSys) { TODO("Хотя, хорошо бы не все в Popup засоывать, а извлечь ChildPopups из hMenu"); InsertMenu(hSys, 0, MF_BYPOSITION|MF_POPUP, (UINT_PTR)hMenu, L"Window menu"); InsertMenu(hSys, 1, MF_BYPOSITION|MF_SEPARATOR, NULL, NULL); } } #endif DWORD nSize = sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_ATTACHGUIAPP); CESERVER_REQ *pIn = ExecuteNewCmd(CECMD_ATTACHGUIAPP, nSize); gnAttachGuiClientFlags = agaf_Success; // С приложенями .Net - приходится работать как с WS_CHILD, // иначе в них "не нажимаются" тулбары и меню if (IsDotNetWindow(hWindow)) { gnAttachGuiClientFlags |= (agaf_DotNet|agaf_WS_CHILD); } // Если в окне нет меню - работаем с ним как с WS_CHILD // так не возникает проблем с активацией и т.д. else if (user->getMenu(hWindow) == NULL) { if (IsQtWindow(asClassA, asClassW)) gnAttachGuiClientFlags |= (agaf_NoMenu|agaf_QtWindow|agaf_WS_CHILD); else gnAttachGuiClientFlags |= (agaf_NoMenu|agaf_WS_CHILD); } pIn->AttachGuiApp.nFlags = gnAttachGuiClientFlags; pIn->AttachGuiApp.nPID = GetCurrentProcessId(); pIn->AttachGuiApp.hAppWindow = hWindow; pIn->AttachGuiApp.Styles.nStyle = nCurStyle; // стили могли измениться после создания окна, pIn->AttachGuiApp.Styles.nStyleEx = nCurStyleEx; // поэтому получим актуальные user->getWindowRect(hWindow, &pIn->AttachGuiApp.rcWindow); GetModuleFileName(NULL, pIn->AttachGuiApp.sAppFilePathName, countof(pIn->AttachGuiApp.sAppFilePathName)); pIn->AttachGuiApp.hkl = (DWORD)(LONG)(LONG_PTR)GetKeyboardLayout(0); wchar_t szGuiPipeName[128]; msprintf(szGuiPipeName, countof(szGuiPipeName), CEGUIPIPENAME, L".", (DWORD)ghConEmuWnd); // AttachThreadInput DWORD nConEmuTID = user->getWindowThreadProcessId(ghConEmuWnd, NULL); DWORD nTID = GetCurrentThreadId(); _ASSERTEX(nTID==gnHookMainThreadId || nTID==gnAttachGuiClientThreadId); BOOL bAttachRc = user->attachThreadInput(nTID, nConEmuTID, TRUE); DWORD nAttachErr = GetLastError(); UNREFERENCED_PARAMETER(bAttachRc); UNREFERENCED_PARAMETER(nAttachErr); HWND hPreFocus = user->getFocus(); CESERVER_REQ* pOut = ExecuteCmd(szGuiPipeName, pIn, 0/*Default timeout*/, NULL); ExecuteFreeResult(pIn); // abStyleHidden == TRUE, если окно при создании указало флаг WS_VISIBLE (т.е. не собиралось звать ShowWindow) if (pOut) { if (pOut->hdr.cbSize > sizeof(CESERVER_REQ_HDR)) { _ASSERTE((pOut->AttachGuiApp.nFlags & agaf_Success) == agaf_Success); BOOL lbRc = FALSE; _ASSERTE(pOut->AttachGuiApp.hConEmuBack && pOut->AttachGuiApp.hConEmuDc && (HWND)pOut->AttachGuiApp.hConEmuDc!=(HWND)pOut->AttachGuiApp.hConEmuBack); _ASSERTE((ghConEmuWndBack==NULL) || (pOut->AttachGuiApp.hConEmuBack==ghConEmuWndBack)); _ASSERTE(ghConEmuWnd && (ghConEmuWnd==pOut->AttachGuiApp.hConEmuWnd)); ghConEmuWnd = pOut->AttachGuiApp.hConEmuWnd; SetConEmuHkWindows(pOut->AttachGuiApp.hConEmuDc, pOut->AttachGuiApp.hConEmuBack); //gbGuiClientHideCaption = pOut->AttachGuiApp.bHideCaption; gGuiClientStyles = pOut->AttachGuiApp.Styles; #ifdef _DEBUG HWND hFocus = user->getFocus(); DWORD nFocusPID = 0; if (hFocus) { user->getWindowThreadProcessId(hFocus, &nFocusPID); DWORD nConEmuPID = 0; user->getWindowThreadProcessId(ghConEmuWnd, &nConEmuPID); if (nFocusPID != GetCurrentProcessId() && nFocusPID != nConEmuPID) { _ASSERTE(hFocus==NULL || (nFocusPID==GetCurrentProcessId() || nFocusPID == nConEmuPID)); hFocus = NULL; } } #endif if (pOut->AttachGuiApp.hkl) { LONG_PTR hkl = (LONG_PTR)(LONG)pOut->AttachGuiApp.hkl; lbRc = ActivateKeyboardLayout((HKL)hkl, KLF_SETFORPROCESS) != NULL; UNREFERENCED_PARAMETER(lbRc); } //grcAttachGuiClientPos = pOut->AttachGuiApp.rcWindow; ReplaceGuiAppWindow(abStyleHidden); //if (hPreFocus) //{ // user->setFocus(hPreFocus); //} UINT nMsgID = user->registerWindowMessageW(CONEMUMSG_RESTORECHILDFOCUS); user->postMessageW(ghConEmuWndBack, nMsgID, 0,0); //// !!! OnSetForegroundWindow не подходит - он дергает Cmd. ////user->setForegroundWindow(ghConEmuWnd); //#if 0 //wchar_t szClass[64] = {}; user->getClassNameW(hFocus, szClass, countof(szClass)); //MessageBox(NULL, szClass, L"WasFocused", MB_SYSTEMMODAL); //#endif ////if (!(nCurStyle & WS_CHILDWINDOW)) //{ // // Если ставить WS_CHILD - пропадет меню! // //nCurStyle = (nCurStyle | WS_CHILDWINDOW|WS_TABSTOP); // & ~(WS_THICKFRAME/*|WS_CAPTION|WS_MINIMIZEBOX|WS_MAXIMIZEBOX*/); // //user->setWindowLongPtrW(hWindow, GWL_STYLE, nCurStyle); // if (gnAttachGuiClientFlags & agaf_DotNet) // { // } // else // { // SetParent(hWindow, ghConEmuWndBack); // } //} // //RECT rcGui = grcAttachGuiClientPos = pOut->AttachGuiApp.rcWindow; //if (user->setWindowPos(hWindow, HWND_TOP, rcGui.left,rcGui.top, rcGui.right-rcGui.left, rcGui.bottom-rcGui.top, // SWP_DRAWFRAME | /*SWP_FRAMECHANGED |*/ (abStyleHidden ? SWP_SHOWWINDOW : 0))) //{ // if (abStyleHidden) // abStyleHidden = FALSE; //} // //// !!! OnSetForegroundWindow не подходит - он дергает Cmd. //user->setForegroundWindow(ghConEmuWnd); ////if (hFocus) ////SetFocus(hFocus ? hFocus : hWindow); // hFocus==NULL, эффекта нет ////OnSetForegroundWindow(hWindow); ////user->postMessage(ghConEmuWnd, WM_NCACTIVATE, TRUE, 0); ////user->postMessage(ghConEmuWnd, WM_NCPAINT, 0, 0); //user->postMessage(hWindow, WM_NCPAINT, 0, 0); } ExecuteFreeResult(pOut); } if (abStyleHidden) { user->showWindow(hWindow, SW_SHOW); } }
HWND WINAPI User32CreateWindowEx(DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam, DWORD dwFlags) { LARGE_STRING WindowName; LARGE_STRING lstrClassName, *plstrClassName; UNICODE_STRING ClassName; WNDCLASSEXA wceA; WNDCLASSEXW wceW; HMODULE hLibModule = NULL; DWORD save_error; BOOL Unicode, ClassFound = FALSE; HWND Handle = NULL; #if 0 DbgPrint("[window] User32CreateWindowEx style %d, exstyle %d, parent %d\n", dwStyle, dwExStyle, hWndParent); #endif if (!RegisterDefaultClasses) { TRACE("RegisterSystemControls\n"); RegisterSystemControls(); } Unicode = !(dwFlags & NUCWE_ANSI); if (IS_ATOM(lpClassName)) { plstrClassName = (PVOID)lpClassName; } else { if(Unicode) RtlInitUnicodeString(&ClassName, (PCWSTR)lpClassName); else { if (!RtlCreateUnicodeStringFromAsciiz(&ClassName, (PCSZ)lpClassName)) { SetLastError(ERROR_OUTOFMEMORY); return (HWND)0; } } /* Copy it to a LARGE_STRING */ lstrClassName.Buffer = ClassName.Buffer; lstrClassName.Length = ClassName.Length; lstrClassName.MaximumLength = ClassName.MaximumLength; plstrClassName = &lstrClassName; } /* Initialize a LARGE_STRING */ RtlInitLargeString(&WindowName, lpWindowName, Unicode); // HACK: The current implementation expects the Window name to be UNICODE if (!Unicode) { NTSTATUS Status; PSTR AnsiBuffer = WindowName.Buffer; ULONG AnsiLength = WindowName.Length; WindowName.Length = 0; WindowName.MaximumLength = AnsiLength * sizeof(WCHAR); WindowName.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, WindowName.MaximumLength); if (!WindowName.Buffer) { SetLastError(ERROR_OUTOFMEMORY); goto cleanup; } Status = RtlMultiByteToUnicodeN(WindowName.Buffer, WindowName.MaximumLength, &WindowName.Length, AnsiBuffer, AnsiLength); if (!NT_SUCCESS(Status)) { goto cleanup; } } if(!hMenu && (dwStyle & (WS_OVERLAPPEDWINDOW | WS_POPUP))) { if(Unicode) { wceW.cbSize = sizeof(WNDCLASSEXW); if(GetClassInfoExW(hInstance, (LPCWSTR)lpClassName, &wceW) && wceW.lpszMenuName) { hMenu = LoadMenuW(hInstance, wceW.lpszMenuName); } } else { wceA.cbSize = sizeof(WNDCLASSEXA); if(GetClassInfoExA(hInstance, lpClassName, &wceA) && wceA.lpszMenuName) { hMenu = LoadMenuA(hInstance, wceA.lpszMenuName); } } } if (!Unicode) dwExStyle |= WS_EX_SETANSICREATOR; for(;;) { Handle = NtUserCreateWindowEx(dwExStyle, plstrClassName, NULL, &WindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam, dwFlags, NULL); if (Handle) break; if (!ClassFound) { save_error = GetLastError(); if ( save_error == ERROR_CANNOT_FIND_WND_CLASS ) { ClassFound = VersionRegisterClass(ClassName.Buffer, NULL, NULL, &hLibModule); if (ClassFound) continue; } } if (hLibModule) { save_error = GetLastError(); FreeLibrary(hLibModule); SetLastError(save_error); hLibModule = 0; } break; } #if 0 DbgPrint("[window] NtUserCreateWindowEx() == %d\n", Handle); #endif cleanup: if(!Unicode) { if (!IS_ATOM(lpClassName)) { RtlFreeUnicodeString(&ClassName); } RtlFreeLargeString(&WindowName); } return Handle; }