【问题标题】:WinAPI ShowWindow fails even though CreateWindowEx seemingly succeeds即使 CreateWindowEx 看似成功,WinAPI ShowWindow 也会失败
【发布时间】:2011-02-27 02:44:59
【问题描述】:

我在使用 CreateWindowEx 时遇到问题。如果我将最终参数 (LPVOID lpParam) 设置为 NULL,并在调用 ShowWindow 时使用返回的窗口句柄,则窗口显示一切正常。但是,我需要传递一个指向类的指针,我将根据我截获的一些操作系统消息来修改该类。当我尝试这样做时,通过将 lpParam 指定为 this,我返回的句柄显然是垃圾,因为将它传递给 ShowWindow 会导致:“一个在用户回调期间遇到未处理的异常。”

我不知道如何调试这个,所以我被卡住了。

指向的地址在传入和拉出之间保持不变。

我没有定义 WM_PAINT 案例。

WM_CREATE 处理程序:

case WM_CREATE:
{

            // get screen resolution
            HWND desktop = GetDesktopWindow();
            RECT R;
            GetWindowRect(desktop, &R);
            int width = R.right - R.left;
            int height = R.bottom - R.top;

            HWND loading_image;
            loading_image = CreateWindowEx(0,L"Static",L"Image", SS_CENTERIMAGE | SS_BITMAP | WS_CHILD | WS_VISIBLE,0,0,width,height,hwnd,(HMENU)ID_IMAGE3,g_hInst,NULL); 
            SetClassLong(loading_image,GCL_STYLE,CS_HREDRAW | CS_VREDRAW);
            HBITMAP bitmap = (HBITMAP)LoadImage(NULL,L"loadingscreen.bmp", IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
            SendMessage(loading_image,STM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)bitmap);

            progressbar = CreateWindowEx(0, PROGRESS_CLASS, (LPTSTR)NULL, WS_CHILD | PBS_SMOOTH | WS_VISIBLE, width/2-400,100,800,20,hwnd,(HMENU)0,g_hInst,NULL);
            SendMessage(progressbar,PBM_SETSTEP,20,NULL);

            CREATESTRUCT* cs = (CREATESTRUCT*)lParam;
            app = (D3DApp*)cs->lpCreateParams;
            return 0;
}

WindowProc 调用在 70 msg (WM_WINDOWPOSCHANGING) 时出错。之前的消息不会变坏:WM_NCCALCSIZE、WM_CREATE、WM_PARENTNOTIFY、WM_SIZE、WM_SIZE 或 WM_SHOWWINDOW,虽然 WM_SHOWWINDOW 是在 WM_WINDOWPOSCHANGING 之前处理的,所以我猜 WM_WINDOWPOSCHANGING 只是 WM_SHOWWINDOW 被通过的结果。

【问题讨论】:

  • 听起来您的WM_CREATE 消息处理程序有问题。你应该发布它。
  • 或者WM_PAINT处理程序有问题。或WM_ERASEBACKGROUND。或WM_POSCHANGING。或者当您的窗口出现时发送的任何内容。
  • WM_CREATEWM_PAINT 之间很可能有一些互动——您应该发布两者的相关来源。

标签: c++ winapi


【解决方案1】:

CreateWindowEx 上放置一个断点。写下你传入的指针。

在 WindowProc 函数上放置一个断点。检查它从您的私有窗口数据中提取的指针(这是您存储指针的位置,对吗?)与传入的指针相同。您正在使用 SetPropGetProp(请参阅 MSDN 上的主题 Window Properties)而不是SetWindowLongPtr,对吧?

在进入 WindowProc 时,打印出消息编号,以便在崩溃时查看正在处理的消息(如果您的调试器支持,您可以为此使用跟踪点,或者在您的代码中添加 printf 调用并重新编译。

【讨论】:

  • 我没有使用SetPropGetPropSetWindowLongPtr。我应该在哪里使用它们?我只是将我的窗口句柄设置为此返回值:CreateWindowEx(WS_EX_TOPMOST, L"D3DWndClassName", L"name", WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT, width, height, NULL, NULL, mhAppInst, this);
  • “我需要传递一个指向类的指针”...如果你把它传递给CreateWindowEx,你会在WM_CREATE中得到它作为CREATESTRUCT的一部分(你已经已经解决了该部分),然后您需要使用SetProp 使其可用于将来的消息。
  • 您有WM_WINDOWPOSCHANGING 的处理程序吗?是否尝试使用 app 指针(在 WM_CREATE 中设置但随后超出范围)?
【解决方案2】:

也许你已经有了答案,但我认为罪魁祸首在于:

SetClassLong(loading_image,GCL_STYLE,CS_HREDRAW | CS_VREDRAW);

为什么需要这样做?

【讨论】:

    【解决方案3】:

    您是否意识到CreateWindowEx 在返回之前发送消息?这意味着您的 WindowProc 必须处理它们。您没有显示该代码,但过早调用 CreateWindowEx 是一个常见错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-13
      • 1970-01-01
      • 2020-11-23
      • 2018-05-24
      • 1970-01-01
      相关资源
      最近更新 更多