0

可能重复:
将指针传递给成员函数

当我离开课堂时WNDPROC DefEditProc;EditKeyProc一切正常。但是现在当我粘贴代码时,编译失败并出现错误error: invalid use of member function (did you forget the '()' ?)。所以我的问题是如何将这段代码压缩到类中,这样我就不会污染全局命名空间?

#include <windows.h>
#include <richedit.h>

class richEdit {
  HWND richeditWindow;
  WNDPROC DefEditProc;
  public:

  LRESULT EditKeyProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    return CallWindowProc(DefEditProc, hwnd, uMsg, wParam, lParam);
  }
  richEdit() {
    HMODULE richedit_library = LoadLibrary("Msftedit.dll");
    if (NULL == richedit_library) abort();

    HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(0);
    richeditWindow = CreateWindowExW (
      WS_EX_TOPMOST,
      MSFTEDIT_CLASS,
      L"window text",
      WS_OVERLAPPED | WS_SYSMENU | ES_MULTILINE | WS_VISIBLE,
      0, 0, 500, 500,
      NULL, NULL, hInstance, NULL
    );
    DefEditProc = (WNDPROC)SetWindowLong(richeditWindow, GWL_WNDPROC, (long)EditKeyProc);
  }
  ~richEdit() {
    MSG msg;
    while( GetMessageW( &msg, richeditWindow, 0, 0 ) ) {
      TranslateMessage( &msg );
      DispatchMessageW( &msg );
    }
  }
};

int main() {
  richEdit re;
}
4

3 回答 3

4

您应该使用自由函数而不是成员函数,因为成员函数具有隐式this参数。您必须声明EditKeyProcstatic CALLBACK,并在需要时找到另一种传递this指针的方法。

static LRESULT CALLBACK EditKeyProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    :::
}

此外,您可以使用SetWindowSubclasswhich 来处理正确的子类化,并为您保留一个额外的指针参数。

于 2013-01-17T20:53:19.680 回答
3

试试这个:

#include <windows.h>
#include <richedit.h>

class richEdit
{
private:
    HWND richeditWindow;
    WNDPROC DefEditProc;

    static LRESULT CALLBACK EditKeyProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        richEdit *pThis = (richEdit*) GetWindowLongPtr(hwnd, GWL_USERDATA);
        return CallWindowProc(pThis->DefEditProc, hwnd, uMsg, wParam, lParam);
    }

public:
    richEdit()
        : richeditWindow(NULL), DefEditProc(NULL)
    {
        HMODULE richedit_library = LoadLibrary("Msftedit.dll");
        if (NULL == richedit_library) abort();

        HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(0);
        richeditWindow = CreateWindowExW (
          WS_EX_TOPMOST,
          MSFTEDIT_CLASS,
          L"window text",
          WS_OVERLAPPED | WS_SYSMENU | ES_MULTILINE | WS_VISIBLE,
          0, 0, 500, 500,
          NULL, NULL, hInstance, NULL
        );
        if (NULL == richeditWindow) abort();

        SetWindowLongPtr(richeditWindow, GWL_USERDATA, (LONG_PTR)this);
        DefEditProc = (WNDPROC) SetWindowLongPtr(richeditWindow, GWL_WNDPROC, (LONG_PTR)&EditKeyProc);
    }

    ~richEdit()
    {
        if (richeditWindow != NULL)
        {
            SetWindowLongPtr(richeditWindow, GWL_WNDPROC, (LONG_PTR)DefEditProc);
            DestroyWindow(richeditWindow);
        }
    }
};

或者:

#include <windows.h>
#include <richedit.h>

namespace myNS
{
    LRESULT CALLBACK richEditKeyProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

    class richEdit
    {
    private:
        HWND richeditWindow;
        WNDPROC DefEditProc;

    public:
        richEdit()
            : richeditWindow(NULL), DefEditProc(NULL)
        {
            HMODULE richedit_library = LoadLibrary("Msftedit.dll");
            if (NULL == richedit_library) abort();

            HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(0);
            richeditWindow = CreateWindowExW (
              WS_EX_TOPMOST,
              MSFTEDIT_CLASS,
              L"window text",
              WS_OVERLAPPED | WS_SYSMENU | ES_MULTILINE | WS_VISIBLE,
              0, 0, 500, 500,
              NULL, NULL, hInstance, NULL
            );
            if (NULL == richeditWindow) abort();

            SetWindowLongPtr(richeditWindow, GWL_USERDATA, (LONG_PTR)this);
            DefEditProc = (WNDPROC) SetWindowLongPtr(richeditWindow, GWL_WNDPROC, (LONG_PTR)&richEditKeyProc);
        }

        ~richEdit()
        {
            if (richeditWindow != NULL)
            {
                SetWindowLongPtr(richeditWindow, GWL_WNDPROC, (LONG_PTR)DefEditProc);
                DestroyWindow(richeditWindow);
            }
        }
    };

    LRESULT CALLBACK richEditKeyProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        richEdit *pThis = (richEdit*) GetWindowLongPtr(hwnd, GWL_USERDATA);
        return CallWindowProc(pThis->DefEditProc, hwnd, uMsg, wParam, lParam);
    }
}
于 2013-01-17T21:32:53.957 回答
0

您不能将指向成员函数的指针用作窗口过程,因为 Windows 需要一个常规函数指针。在内部,它在某些情况下没有足够的存储空间来存储成员指针(在 MSVC 中,它们最多可达 16 个字节,32 位),并且它不知道在任何情况下要使用什么“this”指针。

如果您唯一的兴趣是避免命名空间污染,那么最简单的解决方案是使用命名空间而不是类。否则,您必须使 EditKeyProc 成为该类的静态成员并使用 SetWindowLong 存储“this”指针的副本以供 EditKeyProc 访问。

于 2013-01-17T20:57:06.300 回答