gpt4 book ai didi

c - 我的子类化公共(public)控件工具提示是否会先于我在 WM_DESTROY 中自行销毁?

转载 作者:行者123 更新时间:2023-11-30 15:21:56 26 4
gpt4 key购买 nike

下面的程序创建一个带有公共(public)控件工具提示的窗口,该工具提示对该窗口进行了子类化。当我收到 WM_DESTROY 时,我本能地决定销毁工具提示,因为 WM_DESTROY comes before child (and I assume owned as well) windows are destroyed ,但 DestroyWindow() 失败,返回最后一个错误 1400 (ERROR_INVALID_WINDOW_HANDLE)。 (在 wine 上,它返回 5 (ERROR_ACCESS_DENIED)。我假设这是 wine 的一个错误,要么错误地设置了最后一个错误,要么根本没有设置;我可以稍后提交一个。)

我已经在 Windows XP 32 位和 Windows 7 64 位上进行了测试,使用 Common Controls 5 和 6(下面使用了命令行“标志”),并在 Ubuntu 14.10 和 15.04 beta 上使用 wine 进行了测试。

如果工具提示正在 self 破坏,我可以采取什么措施来处理它?我应该依赖这种行为吗?或者我应该对工具提示进行子类化并自己处理 WM_DESTROY 吗? (两个窗口相互子类化会导致问题吗?)

谢谢。

// 31 march-2 april 2015
#define UNICODE
#define _UNICODE
#define STRICT
#define STRICT_TYPED_ITEMIDS
#define CINTERFACE
// get Windows version right; right now Windows XP
#define WINVER 0x0501
#define _WIN32_WINNT 0x0501
#define _WIN32_WINDOWS 0x0501 /* according to Microsoft's winperf.h */
#define _WIN32_IE 0x0600 /* according to Microsoft's sdkddkver.h */
#define NTDDI_VERSION 0x05010000 /* according to Microsoft's sdkddkver.h */
#include <windows.h>
#include <commctrl.h>
#include <windowsx.h>
#include <stdio.h>
#include <stdlib.h>

void die(char *why)
{
fprintf(stderr, "error %s: %I32u\n", why, GetLastError());
abort();
}

HWND tooltip = NULL;

LRESULT CALLBACK wndproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
CREATESTRUCT *cs = (CREATESTRUCT *) lParam;
TOOLINFOW ti;

switch (uMsg) {
case WM_CREATE:
tooltip = CreateWindowExW(WS_EX_TOOLWINDOW,
TOOLTIPS_CLASSW, L"",
WS_POPUP | TTS_NOPREFIX,
0, 0,
0, 0,
hwnd, NULL, cs->hInstance, NULL);
if (tooltip == NULL)
die("creating tooltip");


ZeroMemory(&ti, sizeof (TOOLINFOW));
ti.cbSize = TTTOOLINFOW_V2_SIZE;
ti.uFlags = TTF_IDISHWND | TTF_SUBCLASS | TTF_TRANSPARENT;
ti.hwnd = hwnd;
ti.uId = (UINT_PTR) hwnd;
ti.hinst = cs->hInstance;
ti.lpszText = L"this is a tooltip! wow!";
if (SendMessageW(tooltip, TTM_ADDTOOL, 0, (LPARAM) (&ti)) == FALSE)
die("setting up tooltip");

break;
case WM_CLOSE:
PostQuitMessage(0);
break;
case WM_DESTROY:
if (DestroyWindow(tooltip) == 0)
die("deleting tooltips");
break;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

void initCommonControls(BOOL);

int main(int argc, char *argv[])
{
BOOL comctl5;
WNDCLASSW wc;
HWND mainwin;
MSG msg;

comctl5 = FALSE;
if (argc > 1)
comctl5 = strcmp(argv[1], "comctl5") == 0;
initCommonControls(comctl5);

ZeroMemory(&wc, sizeof (WNDCLASSW));
wc.lpszClassName = L"mainwin";
wc.lpfnWndProc = wndproc;
wc.hIcon = LoadIconW(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursorW(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
wc.hInstance = GetModuleHandle(NULL);
if (RegisterClassW(&wc) == 0)
die("registering main window class");

mainwin = CreateWindowExW(0,
L"mainwin", L"Main Window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, GetModuleHandle(NULL), NULL);
if (mainwin == NULL)
die("creating main window");

ShowWindow(mainwin, SW_SHOWDEFAULT);
UpdateWindow(mainwin);

while (GetMessage(&msg, NULL, 0, 0) > 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}

// MSDN doesn't list a constant that only includes tooltips but says this and a few others do
#define wantedICCClasses (ICC_BAR_CLASSES)

static ULONG_PTR comctlManifestCookie;
static HMODULE comctl32;

// note that this is an 8-bit character string we're writing; see the encoding clause
static const char manifest[] = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">\n<assemblyIdentity\n version=\"1.0.0.0\"\n processorArchitecture=\"*\"\n name=\"CompanyName.ProductName.YourApplication\"\n type=\"win32\"\n/>\n<description>Your application description here.</description>\n<dependency>\n <dependentAssembly>\n <assemblyIdentity\n type=\"win32\"\n name=\"Microsoft.Windows.Common-Controls\"\n version=\"6.0.0.0\"\n processorArchitecture=\"*\"\n publicKeyToken=\"6595b64144ccf1df\"\n language=\"*\"\n />\n </dependentAssembly>\n</dependency>\n</assembly>\n";

void initCommonControls(BOOL comctl5)
{
WCHAR temppath[MAX_PATH + 1];
WCHAR filename[MAX_PATH + 1];
HANDLE file;
DWORD nExpected, nGot;
ACTCTX actctx;
HANDLE ac;
INITCOMMONCONTROLSEX icc;
FARPROC f;
// this is listed as WINAPI in both Microsoft's and MinGW's headers, but not on MSDN for some reason
BOOL (*WINAPI ficc)(const LPINITCOMMONCONTROLSEX);

if (!comctl5) {
if (GetTempPathW(MAX_PATH + 1, temppath) == 0)
die("getting temporary path for writing manifest file");
if (GetTempFileNameW(temppath, L"manifest", 0, filename) == 0)
die("getting temporary filename for writing manifest file");
file = CreateFileW(filename, GENERIC_WRITE,
0, // don't share while writing
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (file == NULL)
die("creating manifest file");
nExpected = (sizeof manifest / sizeof manifest[0]) - 1; // - 1 to omit the terminating null character)
if (WriteFile(file, manifest, nExpected, &nGot, NULL) == 0)
die("writing manifest file");
if (nGot != nExpected)
die("short write to manifest file");
if (CloseHandle(file) == 0)
die("closing manifest file (this IS an error here because not doing so will prevent Windows from being able to use the manifest file in an activation context)");

ZeroMemory(&actctx, sizeof (ACTCTX));
actctx.cbSize = sizeof (ACTCTX);
actctx.dwFlags = ACTCTX_FLAG_SET_PROCESS_DEFAULT;
actctx.lpSource = filename;
ac = CreateActCtx(&actctx);
if (ac == INVALID_HANDLE_VALUE)
die("creating activation context for synthesized manifest file");
if (ActivateActCtx(ac, &comctlManifestCookie) == FALSE)
die("activating activation context for synthesized manifest file");
}

ZeroMemory(&icc, sizeof (INITCOMMONCONTROLSEX));
icc.dwSize = sizeof (INITCOMMONCONTROLSEX);
icc.dwICC = wantedICCClasses;

comctl32 = LoadLibraryW(L"comctl32.dll");
if (comctl32 == NULL)
die("loading comctl32.dll");
f = GetProcAddress(comctl32, "InitCommonControlsEx");
if (f == NULL)
die("loading InitCommonControlsEx()");
ficc = (BOOL (*WINAPI)(const LPINITCOMMONCONTROLSEX)) f;
if ((*ficc)(&icc) == FALSE)
die("initializing Common Controls (comctl32.dll)");
}

最佳答案

工具提示没有 WS_CHILD 样式。所有此类窗口在所有者窗口收到 WM_DESTROY 之前就被完全销毁。结果 DestroyWindow(tooltip) 并返回错误 - ERROR_INVALID_WINDOW_HANDLE

关于c - 我的子类化公共(public)控件工具提示是否会先于我在 WM_DESTROY 中自行销毁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29419291/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com