【问题标题】:Static HWND - Why is it necessary?静态 HWND - 为什么有必要?
【发布时间】:2015-10-17 17:33:26
【问题描述】:

好吧,我问的唯一原因是因为我读到 HWND 是一个指针,指针会更改原始值,而不是创建存储在该内存位置的副本。

但它实际上并不像一个指针,我之所以这么说是因为如果我有一个 switch 语句,示例:

void ExampleFunction(int iSwitch)
{
    HWND hButton;

    switch (iSwitch)
    {
     case 1:
     hButton = CreateWindow( Blah Blah blah); //<-- Shouldn't it return to hButton's location.
     break;

     case 2: 
     ShowWindow(hButton, SW_SHOW); //<-- Ops forgot what was stored in hButton.
     break;
    }
}

但是作为一个新的C++ Win32程序员,不应该忘记吗?只需定位内存地址,然后抓取里面的内容。除非内存地址改变等。

我真的不知道,你介意详细说明吗?谢谢。

【问题讨论】:

  • 请尝试创建Minimal, Complete, and Verifiable Example,因为问题中的代码缺少很多上下文。
  • 将 HWND 视为标识窗口的值。您所要做的就是将它传递给需要知道您引用哪个窗口的函数。
  • “指针更改原始值,而不是创建存储在该内存位置的副本” 这是一种非常简单且不准确的指针定义方式。
  • @Lightness Races in Orbit - 阅读书籍时,它们往往会给你一种描述事物的简单方式,而不是仅仅用 5 章来描述指针是什么。所以我只是复制了我从阅读 C++ Primer Plus 第 6 版中听到的内容。
  • @TrevinCorkery:好的,但我也说“不准确”。它让你产生了这种误解。这不是说什么吗?

标签: c++ winapi static hwnd


【解决方案1】:

这可能不是最高质量的答案;欢迎提出改进建议。

假设 HWND 的值永远不会改变,而 HWND 指向的窗口保持活动状态是正确的。

我猜你写的代码是这样的:

LRESULT CALLBACK wndproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    HWND button;

    switch (uMsg) {
    case WM_CREATE:
        button = CreateWindowEx(...);
        break;
    case WM_COMMAND:
        if (lParam == (LPARAM) button)
            /* button was clicked; do something */;
    }
    return DefWindowProc(...);
}

想知道为什么它不起作用,但正在改变

    HWND button;

    static HWND button;

修复它。

这不是 HWND 的属性。代码失败并不是因为 HWND 的值发生了变化。其实这和windows一点关系都没有,和c有关系。

代码不起作用的原因是变量 button 是在每次调用wndproc() 函数时重新创建的。看,一个窗口过程被调用了很多次,对于窗口在整个程序执行过程中收到的每条消息都调用一次。每次,您都会获得一个全新的button 变量,而button 变量在之前调用中的值会丢失。指针仍然存在,但它没有存储在任何变量或任何其他内存位置!窗户没有被破坏。你只是不能再通过正常的方式得到它了。

static 所做的是告诉 C 你希望变量在每个函数调用中都保留。所以现在对窗口过程的每次调用都有相同的button,并且该指针值不再丢失。

这是一个快速修复,它并不能很好地扩展到非常大的项目。在这些情况下,包含窗口句柄、(可能)全局变量或使用GWLP_USERDATA 或其他cbWndExtra 字节的结构会更好。我想一个更好的问题是为什么这个快速修复不断被建议作为其他人在 Stack Overflow 上的类似问题的解决方案(或者至少没有解释为什么它是一个快速修复),但这是我们必须考虑的事情一个社区。​​p>

请记住,默认情况下,在大多数语言(不仅仅是 C 和 C++!)中,函数的局部变量仅在每个单独的函数调用期间存在。

【讨论】:

    【解决方案2】:

    问题中的代码缺少很多上下文(所以只是在这里盲目猜测),但是如果代码在单独的函数中并且变量hButton是该函数中的局部变量,那么你必须记住局部变量在它们所在的函数返回时超出范围,并且下次调用该函数时,该变量是一个全新的变量,该变量对于该调用是唯一的,并且只有该调用。

    另外值得一提的是,非静态局部变量不会以任何方式自动初始化。如果您没有显式初始化此类变量,则其值将是不确定,并且以任何方式使用它(初始化它除外)都会导致未定义的行为

    【讨论】:

    • 这不是我的实际代码,我知道它丢失了很多,因为我没有复制和粘贴,我只是把它写在这里作为示例,感谢您向我描述。我现在明白你可能的意思了,HWND 和 Switch 都在同一个功能中,所以我将编辑主要帖子以使其更清楚。
    • 这不是我的实际代码我知道它丢失了很多因为我没有复制和粘贴,我只是在这里写出来作为示例,感谢您将其描述为我。 请永远不要那样做。不要发布假代码。不要浪费大家的时间。
    猜你喜欢
    • 1970-01-01
    • 2014-05-27
    • 1970-01-01
    • 2012-04-11
    • 1970-01-01
    • 2012-09-08
    • 2011-01-14
    • 1970-01-01
    相关资源
    最近更新 更多