C++ 自定义窗口进程在单独的文件中

C++ 自定义窗口进程在单独的文件中,c++,winapi,global-variables,subclassing,C++,Winapi,Global Variables,Subclassing,我目前正在学习winapi,希望获得一些关于如何使用不同窗口过程设置自定义控件的建议 假设我有20个按钮。我希望鼠标悬停在每个按钮上时,每个按钮的响应都不同。比方说,“退出”按钮在悬停时绘制一个红色矩形,或者在其他按钮悬停时绘制一个蓝色矩形 因此,我设置了一个自定义控制过程,用于处理鼠标单击、鼠标悬停等操作,并存储在custom.cpp中。在main.cpp中,有一个MainProc(),它使用 CustomProcHandler = (WNDPROC)SetWindowLong(hwndBut

我目前正在学习winapi,希望获得一些关于如何使用不同窗口过程设置自定义控件的建议

假设我有20个按钮。我希望鼠标悬停在每个按钮上时,每个按钮的响应都不同。比方说,“退出”按钮在悬停时绘制一个红色矩形,或者在其他按钮悬停时绘制一个蓝色矩形

因此,我设置了一个自定义控制过程,用于处理鼠标单击、鼠标悬停等操作,并存储在
custom.cpp
中。在
main.cpp
中,有一个
MainProc()
,它使用

CustomProcHandler = (WNDPROC)SetWindowLong(hwndButton, GWL_WNDPROC, (long)CustomProc)
主要条款h:

#include <windows.h>
#include <iostream>
using namespace std;

const char g_szClassName[] = "Applicaton";
static HWND hwnd, hwndButton;
static HINSTANCE hInst;
static WNDPROC buttonProcHandler;


LRESULT CALLBACK MainProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK ButtonProc(HWND, UINT, WPARAM, LPARAM);
custom.cpp:

#include "main.h"

LRESULT CALLBACK ButtonProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){
    switch(msg){
        case WM_CREATE:
            break;
        case WM_MOUSEMOVE:
            break;
        case WM_LBUTTONDOWN:
            break;
        default:
            return CallWindowProc(buttonProcHandler, hwnd, msg, wParam, lParam);
    }
    return 0;
}
问题是按钮消失了。。。但是当我在
main.cpp
中移动
buttonProc()
时,一切都正常

所以,我猜我在声明全局变量时出错了,比如
静态WNDPROC buttonProcHandler

我知道我所做的是完全错误的,而且还有更好的方法。我只是不知道那是什么


有人能帮我/教我创建自定义过程的标准方法吗?

你对
静态
的工作原理有一个基本的误解。由于将
main.h
包含在单独的
.cpp
文件中,因此每个
.cpp
都会获得
main.h
声明的
静态
变量的本地副本。如果您希望多个
.cpp
文件彼此共享全局变量,请不要在共享的
.h
文件中将它们声明为
静态
,在单个
.cpp
文件中定义一次,然后在共享的
.h
文件中使用
外部
声明。此外,当您开始对多个按钮进行子类化时,每个按钮都需要单独的
WNDPROC
变量,因为您必须将之前的
WNDPROC
正确地分配到
CallWindowProc()
,因此不能对所有按钮使用单个
WNDPROC
变量。处理此问题的最佳方法是将每个按钮包装在一个类中,该类处理它所持有的单个按钮的子类。您应该使用
SetWindowLongPtr
(LONG_PTR)ButtonProc
,否则指针值可能会被剪切。太棒了,它工作起来很有魅力!谢谢你,雷米·勒博先生@VTT:除非你下定决心支持Win9x和Windows 2000,否则你不应该这样做。控件子类化的正确方法是调用
SetWindowSubclass
,如中所述。
#include "main.h"

LRESULT CALLBACK ButtonProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){
    switch(msg){
        case WM_CREATE:
            break;
        case WM_MOUSEMOVE:
            break;
        case WM_LBUTTONDOWN:
            break;
        default:
            return CallWindowProc(buttonProcHandler, hwnd, msg, wParam, lParam);
    }
    return 0;
}