【问题标题】:Set HWND on CreateWindow appears to fail在 CreateWindow 上设置 HWND 似乎失败
【发布时间】:2011-12-23 09:12:00
【问题描述】:

我来自 C# 并且对此非常陌生,所以请多多包涵。

我有一个 MainWindow 类,它有一些私有的 HWND 变量。一个用于窗口本身,一个用于每个控件。我想我需要跟踪它们,或者以后会更容易?

无论如何,我有:

class GUIMain
{
private:
    HINSTANCE hInstance;
    HWND hWnd; // The windows itself
    HWND cmdGenerate, cmdQuit; // 2 buttons

我有一个名为 initialise(HWND hWnd) 的私有方法,它在 WM_CREATE 上调用,它将所有控件添加到窗口:

void MainWindow::initialise(HWND hWnd)
{
  this->hWnd = hWnd;

  cmdGenerate = CreateWindow(TEXT("BUTTON"), TEXT("&Generate..."),
                             WS_VISIBLE | WS_CHILD,
                             6, 6, 150, 25,        
                             hWnd, (HMENU)1, 0, 0);

  cmdQuit     = CreateWindow(TEXT("BUTTON"), TEXT("&Quit"),
                             WS_VISIBLE | WS_CHILD,
                             6, 37, 150, 25,        
                             hWnd, (HMENU)2, 0, 0);
}

但是这似乎并没有将按钮放在窗口上。事实上,当我调试时,我可以看到它甚至没有超过第一行。奇怪的是,当我把它改成这样:

void MainWindow::initialise(HWND hWnd)
{
  //this->hWnd = hWnd;

  /*cmdGenerate = */CreateWindow(TEXT("BUTTON"), TEXT("&Generate..."),
                                 WS_VISIBLE | WS_CHILD,
                                 6, 6, 150, 25,        
                                 hWnd, (HMENU)1, 0, 0);

  /*cmdQuit     = */CreateWindow(TEXT("BUTTON"), TEXT("&Quit"),
                                 WS_VISIBLE | WS_CHILD,
                                 6, 37, 150, 25,        
                                 hWnd, (HMENU)2, 0, 0);
}

它似乎工作正常。

逻辑似乎表明将 HWND 私有变量的值分配给 CreateWindow 函数返回值会导致问题,但我之前已经这样做过并且没有问题?

我之前的代码和这段代码的唯一区别是我现在使用的是类,而之前(在我学习的时候)我只是在 WinMain 和 WndProc 中拥有所有东西。

WinMain:http://pastebin.com/j54vW9gc
头文件:http://pastebin.com/cUs4vVJ6
CPP 文件:http://pastebin.com/B5KUXTvx

【问题讨论】:

  • 似乎一个应该工作,另一个应该工作。你能告诉我们你的 WndProc 吗?您说初始化(sp)是私有的,并且从 WM_CREATE 调用。 wndproc 是静态成员函数吗?对象在哪里创建?
  • 我附上了完整源代码的链接。
  • 听起来你的 this 指针不正确。
  • @AlfP.Steinbach 这怎么可能?这样的事情在 C# 中是不可能发生的 :(
  • @Ozzah:请参阅下面 Joe McGrath 的回答。

标签: c++ windows winapi createwindow


【解决方案1】:

欢迎来到不是为 C++ 设计的 win32 世界。这是一个很好的第一次尝试。我重做了数百次尝试制作通用框架的类,然后才说它不值得再花时间了。

您的 WinMain() 也会有所帮助,但我看到的一个大问题是您致电 CreateWindowEx() 。您发送的最后一个参数是 0。当您稍后检索它时SetWindowLong(hWnd, GWL_USERDATA, (long) ((LPCREATESTRUCT)lParam)->lpCreateParams); 您说它是指向类的指针。你的意思是:

         hWnd = CreateWindowEx(0, TEXT("AS2MainWindow"),
                                              TEXT("AS2"),
                                              WS_BORDER | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
                                              CW_USEDEFAULT, CW_USEDEFAULT,
                                              824, 350,
                                              0, 0,
                                              hInstance, this);

寻找其他问题。看看是否有帮助。如果不是,也许你的帖子你的 main()

添加: CreateWindowEx

HWND WINAPI CreateWindowEx(
  __in      DWORD dwExStyle,
  __in_opt  LPCTSTR lpClassName,
  __in_opt  LPCTSTR lpWindowName,
  __in      DWORD dwStyle,
  __in      int x,
  __in      int y,
  __in      int nWidth,
  __in      int nHeight,
  __in_opt  HWND hWndParent,
  __in_opt  HMENU hMenu,
  __in_opt  HINSTANCE hInstance,
  __in_opt  LPVOID lpParam
);

最后一个参数lpParam 是可选的。因此,当您将其设置为 0 时,它不会造成任何伤害。但这就是你如何向你的WM_NCCREATE 或WM_CREATE“发送”一些东西的方式。它可以是任何 LPVOID。在 C 语言中,您可以发送一个指向结构或任何您想要的东西的指针。在这种情况下,您希望向它发送一个指向与您的窗口有关的对象的指针。

要在 WM_NCCREATE 或 WM_CREATE 中获取此参数,请使用以下代码:

(long) ((LPCREATESTRUCT)lParam)->lpCreateParams);

也就是说将lParam 转换为pointer 转换为CREATESTRUCT。比从中获取lpCreateParams。并将其转换为long。这与我编写这段难以理解的代码的方式略有不同。如果你把它分成几个步骤,它看起来更容易。如果您需要进一步的解释,请告诉我。

下面的全图是 CreateStruct 的定义。它不仅包含 lpCreateParams。 (您选择作为指向您的类的指针)。

typedef struct tagCREATESTRUCT {
  LPVOID    lpCreateParams;
  HINSTANCE hInstance;
  HMENU     hMenu;
  HWND      hwndParent;
  int       cy;
  int       cx;
  int       y;
  int       x;
  LONG      style;
  LPCTSTR   lpszName;
  LPCTSTR   lpszClass;
  DWORD     dwExStyle;
} CREATESTRUCT, *LPCREATESTRUCT;

了解了这一切之后。查看 ATL thunking。如果您希望所有代码都在类中,那么这是要走的路。我发现最好避免每段代码都在一个类中,而不必如此。取决于我正在编写的程序。

【讨论】:

  • 这似乎解决了它!为什么我需要在 CreateWindowEx 中传递 this,即使我使用 SetWindowLong 设置指针?这两个指针有什么区别?
  • 添加到答案,因为相当长的解释。
  • 没关系,我想通了!这是因为当我去((LPCREATESTRUCT)lParam)->lpCreateParams 时,它必须来自某个地方,那就是来自我给CreateWindowEx 的this 指针,对吧? :)
  • 正确。你得到的比大多数人都好。查看 ATL thunking,您似乎对正在发生的事情有很好的了解。比切换到 linux 并在这里只回答 win32 问题:)
  • @JoeMcGrath:实际上很有可能在 Windows API 之上制作一个非常好的包装器,而不仅仅是瘦包装器。 (我已经做过一次了,Qt 和 wxWidgets 也是如此。)但这绝对不是微不足道的,因为 WinAPI 是在当时 C++ 是“C with Classes”时设计的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-05-20
  • 1970-01-01
  • 2012-12-27
  • 2016-04-05
  • 2018-12-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多