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

メンバー関数には暗黙のパラメーターがあるため、メンバー関数の代わりにフリー関数を使用することになっています。として宣言する必要があり、必要に応じてポインターを渡す別の方法を見つける必要があります。thisEditKeyProcstatic CALLBACKthis

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

SetWindowSubclassさらに、適切なサブクラス化を処理し、追加のポインター引数を保持する whichを使用できる場合があります。

于 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を使用して、EditKeyProcがアクセスするための「this」ポインターのコピーを格納する必要があります。

于 2013-01-17T20:57:06.300 に答える