求助:窗口过程的问题!

qingsebaobei 2009-08-06 10:50:06
#include <windows.h>

#define ID_LIST 1

#define DIRATTR (DDL_READWRITE|DDL_READONLY| DDL_SYSTEM |DDL_DIRECTORY)
LRESULT CALLBACK listproc(HWND,UINT,WPARAM,LPARAM);
LRESULT CALLBACK WinProc(HWND,UINT,WPARAM,LPARAM);
WNDPROC oldproc;
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
static TCHAR szAppName[]=TEXT("MyApp");
MSG msg;
HWND hwnd;
WNDCLASS wndcls;
wndcls.cbClsExtra=0;
wndcls.cbWndExtra=0;
wndcls.hbrBackground=(HBRUSH)GetStockObject(COLOR_BTNFACE+1);
wndcls.hCursor=LoadCursor(NULL,IDC_ARROW);
wndcls.hIcon=LoadIcon(NULL,NULL);
wndcls.hInstance=hInstance;
wndcls.lpfnWndProc=WinProc;
wndcls.lpszClassName=szAppName;
wndcls.lpszMenuName=NULL;
wndcls.style=CS_HREDRAW | CS_VREDRAW;
RegisterClass(&wndcls);
hwnd=CreateWindow(szAppName,"app",
WS_CAPTION | WS_SYSMENU,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
NULL,NULL,hInstance,NULL);
ShowWindow(hwnd,SW_SHOWNORMAL);
UpdateWindow(hwnd);
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WinProc(HWND hwnd,UINT message,WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_CREATE:
hwndlist=CreateWindow(TEXT("listbox"),NULL,WS_CHILDWINDOW|WS_VISIBLE|LBS_STANDARD | WS_BORDER,
150,45,180,200,hwnd,(HMENU)ID_LIST,(HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),NULL);

oldproc=(WNDPROC)SetWindowLong(hwndlist,GWL_WNDPROC,(LPARAM)listproc);
return 0;
case WM_PAINT:
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hwnd,message,wParam,lParam);
}
return 0;
}


LRESULT CALLBACK listproc(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam)
{
if((message==WM_KEYDOWN)&&(wparam==VK_RETURN))
SendMessage(GetParent(hwnd),WM_COMMAND,MAKELONG(1,LBN_DBLCLK),(LPARAM)hwnd);
return CallWindowProc(oldproc,hwnd,message,wparam,lparam);
}

oldproc=(WNDPROC)SetWindowLong(hwndlist,GWL_WNDPROC,(LPARAM)listproc);
这个意思是说将hwndlist的窗口过程换成listproc而不用主窗口的窗口过程吗?

return CallWindowProc(oldproc,hwnd,message,wparam,lparam);
那这个oldproc又是什么意思呢?oldproc不是在上面等于listproc。可是我看有的地方说
是如在本程序中只处理if((message==WM_KEYDOWN)&&(wparam==VK_RETURN))这个,其他消息
就交给上一个窗口过程程序。这上一个窗口过程我理解可能是主窗口的处理程序。只是这里
用oldproc=(WNDPROC)SetWindowLong(hwndlist,GWL_WNDPROC,(LPARAM)listproc);后将hwndlist
这个子窗口的窗口过程从WndProc换成了listproc.但return CallWindowProc(oldproc,hwnd,message,wparam,lparam);
我又不明白了,我认为应该是CallWindowProc(Wndproc,hwnd,message,wparam,lparam);
这样才是把消息发给以前的窗口过程,就是父窗口处理程序才对啊。
各位友友谁能给我解释一下SetWindowLong和CallWindowProc
到底是怎么是怎么换窗口过程,又是怎么把不处理的消息交给以前的窗口过程处理的,
谢谢大家了。
...全文
186 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
scsnsjsl_cs_dn 2009-08-09
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 wltg2001 的回复:]
oldproc=(WNDPROC)SetWindowLong(hwndlist,GWL_WNDPROC,(LPARAM)listproc); 这个API的功能是将窗口的处理函数进行修改,上面的作用是将list控件的处理过程由窗口类指定的默认处理过程改为listproc,上面这个做法一般又叫做窗口子类化,也就是将默认的处理过程改成你自定义的过程,它的返回值oldproc是一个函数指针,针向原来的窗口处理函数,也就是说,现在oldproc现在相当于是这个控件的默认处理函数了。之所以这样做,是因为窗口子类化一般只是用来处理一些特殊消息,对特殊消息作特殊处理,上面的例子从代码上看是想对键盘的回车键进行特殊处理,从代码上看它是想将回车模拟成鼠标双击事件,所以在它的处理函数中用SendMessage向父窗口发送消息。
在窗口子类化中,对于它不处理的消息,还是要由原来的处理函数进行处理,原来的处理函数由oldproc保存着呢,所以最后调用return CallWindowProc(listproc,hwnd,message,wparam,lparam)
楼主两个地方理解错了,一个是oldproc是什么不知道,它是由SetWindowLong返回的,并不是listproc,而控件的原来的内置处理函数
第二个错误在于:其他消息就交给上一个窗口过程程序。这上一个窗口过程我理解可能是主窗口的处理程序。
这里上一个窗口过程不是主窗口处理程序,而是控件本身内置的处理过程。
[/Quote]
wltg2001 2009-08-07
  • 打赏
  • 举报
回复
我看楼主没有明白是每一个控件本身也是窗口,所以每个控件本身在系统内部有一个窗口处理过程,楼主可能没有意识到这个内置的窗口处理过程,将它和父窗口处理过程弄混了。
xylicon 2009-08-07
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 qingsebaobei 的回复:]
是不是这样。
就是在Listproc 里只拦截if((message==WM_KEYDOWN)&&(wparam==VK_RETURN))
这个消息,如果是这个消息就处理。如果不是这个消息就交个WndProc来处理。
大概是这个意思吗?

[/Quote]

交不交给原来的窗口过程。是你决定的,你调用了return CallWindowProc(oldproc,hwnd,message,wparam,lparam); 就交给原来的窗口过程,要是return 0或者其他值,就不会再交给原来的窗口过程处理了。

[Quote=引用 6 楼 qingsebaobei 的回复:]
当程序的子窗口 收到消息 全部交给 ListProc来处理。而在ListProc只处理按下接盘回车键。如果是
别的消息,就通过CallWindowProc将这个消息交给WndProc就是父窗口的处理程序来处理?
[/Quote]
按照你的代码来看
LRESULT CALLBACK listproc(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam) 
{
if((message==WM_KEYDOWN)&&(wparam==VK_RETURN))
SendMessage(GetParent(hwnd),WM_COMMAND,MAKELONG(1,LBN_DBLCLK),(LPARAM)hwnd);
return CallWindowProc(oldproc,hwnd,message,wparam,lparam);
}


是当程序的子窗口 收到消息,先到listproc中去处理,然后再return CallWindowProc(oldproc,hwnd,message,wparam,lparam);
到oldproc去处理。

也就是说,拦截消息处理完后,还是交给oldproc的。即使if((message==WM_KEYDOWN)&&(wparam==VK_RETURN)) 是这2个消息在listproc中处理过了,但还是会在oldproc中去处理一次。
见习学术士 2009-08-07
  • 打赏
  • 举报
回复
看来楼主明白了
wltg2001 2009-08-07
  • 打赏
  • 举报
回复
oldproc=(WNDPROC)SetWindowLong(hwndlist,GWL_WNDPROC,(LPARAM)listproc); 这个API的功能是将窗口的处理函数进行修改,上面的作用是将list控件的处理过程由窗口类指定的默认处理过程改为listproc,上面这个做法一般又叫做窗口子类化,也就是将默认的处理过程改成你自定义的过程,它的返回值oldproc是一个函数指针,针向原来的窗口处理函数,也就是说,现在oldproc现在相当于是这个控件的默认处理函数了。之所以这样做,是因为窗口子类化一般只是用来处理一些特殊消息,对特殊消息作特殊处理,上面的例子从代码上看是想对键盘的回车键进行特殊处理,从代码上看它是想将回车模拟成鼠标双击事件,所以在它的处理函数中用SendMessage向父窗口发送消息。
在窗口子类化中,对于它不处理的消息,还是要由原来的处理函数进行处理,原来的处理函数由oldproc保存着呢,所以最后调用return CallWindowProc(listproc,hwnd,message,wparam,lparam)
楼主两个地方理解错了,一个是oldproc是什么不知道,它是由SetWindowLong返回的,并不是listproc,而控件的原来的内置处理函数
第二个错误在于:其他消息就交给上一个窗口过程程序。这上一个窗口过程我理解可能是主窗口的处理程序。
这里上一个窗口过程不是主窗口处理程序,而是控件本身内置的处理过程。
qingsebaobei 2009-08-07
  • 打赏
  • 举报
回复
当程序的子窗口 收到消息 全部交给 ListProc来处理。而在ListProc只处理按下接盘回车键。如果是
别的消息,就通过CallWindowProc将这个消息交给WndProc就是父窗口的处理程序来处理?
qingsebaobei 2009-08-07
  • 打赏
  • 举报
回复
是不是这样。
就是在Listproc 里只拦截if((message==WM_KEYDOWN)&&(wparam==VK_RETURN))
这个消息,如果是这个消息就处理。如果不是这个消息就交个WndProc来处理。
大概是这个意思吗?
jasonM2008 2009-08-07
  • 打赏
  • 举报
回复
oldproc=(WNDPROC)SetWindowLong(hwndlist,GWL_WNDPROC,(LPARAM)listproc);
这个意思是说将hwndlist的窗口过程换成listproc而不用主窗口的窗口过程吗?

不是不用主窗口过程,而是不用默认的listbox的窗口过程,用自己的窗口过程来替换!!

return CallWindowProc(oldproc,hwnd,message,wparam,lparam);
因为你在上一步骤把先前的LISTBOX的默认窗口过程替换了,这次是调用先前的窗口过程!!!
xylicon 2009-08-07
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 qingsebaobei 的回复:]
那return CallWindowProc(oldproc,hwnd,message,wparam,lparam);
中的oldproc就是Wndproc的地址吗?先前不是已经把oldproc=listproc,那现在再用
oldproc做参数不是就相当于
return CallWindowProc(listproc,hwnd,message,wparam,lparam); 吗?
[/Quote]

oldproc 是上一个窗口过程,也就是你这里用listproc的窗口过程拦截了窗口消息,而当你完成你的窗口过程之后,希望上一个窗口过程,也就是之前那个窗口过程也能得到处理,你就调用return CallWindowProc(oldproc,hwnd,message,wparam,lparam);

这个之前的窗口过程,一般是默认的窗口过程,所以这里调用return CallWindowProc(oldproc,hwnd,message,wparam,lparam);
是为了你的窗口的一些消息,特别是没被拦截的窗口消息得到默认的处理。
socoola 2009-08-07
  • 打赏
  • 举报
回复
SetWindowLong(hwndlist,GWL_WNDPROC,(LPARAM)listproc)返回的是替换之前的函数指针,而不是listproc
qingsebaobei 2009-08-07
  • 打赏
  • 举报
回复
那return CallWindowProc(oldproc,hwnd,message,wparam,lparam);
中的oldproc就是Wndproc的地址吗?先前不是已经把oldproc=listproc,那现在再用
oldproc做参数不是就相当于
return CallWindowProc(listproc,hwnd,message,wparam,lparam); 吗?
内容概要:本文提出了一种基于Token(JWT)与Redis协同的高性能Session管理方案,专为银行业在开放银行、多终端接入和高并发场景下的身份认证与安全管理需求而设计。方案采用“JWT + Redis黑名单/白名单”的混合架构,结合双Token机制(Access Token与Refresh Token),解决传统Session模式跨域困难及纯JWT不可撤销的问题。通过RSA非对称加密、Redis原子操作(Lua脚本)、多租户Key隔离、设备绑定校验等技术手段,实现安全可控的身份认证体系,并详细展示了在Spring Cloud Gateway网关集成、业务服务上下文传递等方面的完整代码实现。; 适合人群:具备Java开发基础,熟悉Spring Boot、微服务架构及Redis应用,从事金融系统或高安全要求平台研发的技术人员,尤其是工作3年以上的中高级后端开发者; 使用场景及目标:①构建适用于银行级系统的无状态但可管控的Session管理机制;②实现跨平台(Web/移动端/小程序)统一认证;③支持多租户SaaS化部署下的会话隔离;④满足强合规要求下的账号强制下线、Token吊销与审计追踪能力; 阅读建议:此资源强调理论与实战结合,不仅阐述架构设计理念,还提供可落地的完整代码示例,建议读者结合Spring生态实际项目进行调试与扩展,重点关注Token生命周期管理、Redis数据结构设计及网关层与业务层的协作模式。
学籍照片批处理工具 - 用户操作说明 感谢您使用本软件!本工具可批量处理学籍照片,集成人脸智能裁剪、AI 自动抠图换背景、尺寸缩放、图片压缩等核心功能,适配学校、培训机构等场景,快速统一标准化证件照。 一、软件安装与激活 1.获取软件 您将获得独立程序文件:学籍照片处理工具.exe,绿色免安装,直接双击即可运行。 二、软件主界面介绍 整体界面划分为六大功能区域,布局清晰、操作直观: 1.文件路径区:选择输入文件夹(存放原始照片)、输出文件夹(保存成品照片); 2.处理参数区:自定义输出尺寸、扩展比例、图片格式、文件大小限制; 3.AI 抠图功能区:一键启用智能抠图,支持白 / 浅蓝 / 红 / 自定义底色替换; 4.快捷操作区:包含【开始处理】【取消处理】核心按钮; 5.处理日志区:实时刷新处理进度、运行状态、错误提示; 6.状态栏:展示软件运行状态、版本信息。 三、基本操作流程 步骤 1:准备原始照片 •将所有待处理照片统一放入同一个文件夹,支持 JPG、PNG、BMP 主流格式; •要求人像面部清晰无遮挡,原始背景尽量简洁,提升识别与处理成功率。 步骤 2:设置处理参数 1.输入文件夹:点击「浏览」,选中存放原始照片的文件夹; 2.输出文件夹:点击「浏览」,自定义成品照片保存目录; 3.输出尺寸:默认标准学籍照 413×579 像素,可手动自定义修改; 4.扩展比例:默认 2.2,控制上半身裁剪范围,数值越大,保留肩部范围越多;推荐取值:1.8~2.5; 5.输出格式:可选 JPG(通用推荐)、PNG(透明背景)、BMP(无损画质,体积偏大); 6.文件大小限制:勾选开启压缩功能,自定义阈值(单位:KB),满足平台上传大小要求,如学籍照限制 50KB 可直接填写数值。 步骤 3:设置 AI 抠图换背景(可选) 1.默认勾选【启用 AI 智能抠图】,无需额外配置即可使用;
内容概要:本文围绕银行业务中Session管理的安全性与性能优化展开,深入分析了银行系统面临的Session劫持、固定、CSRF及并发登录等安全威胁,并提出工程级防御策略。通过“登录—交易—退出”全流程代码示例,展示了登录后重建Session、多因素绑定、权限与限额控制、操作留痕及风控前置等核心机制的实际应用。同时介绍了基于本地缓存(Caffeine)与Redis构成的二级缓存架构,以提升高并发下的响应性能,并探讨了未来发展方向,如生物特征动态评估、边缘计算校验和隐私增强技术,实现安全与体验的平衡。; 适合人群:具备Java开发基础,熟悉Web安全机制,从事金融系统或高安全性要求系统设计与开发的技术人员,尤其是工作2-5年的中高级研发或安全工程师。; 使用场景及目标:①构建抗攻击能力强的银行级会话管理体系;②实现权限、风控、审计一体化的Session控制方案;③优化大规模并发场景下的会话存储与查询性能;④为金融类应用提供可追溯、可扩展的身份会话管理参考模型。; 阅读建议:本文结合代码与架构设计,建议读者重点关注登录重建Session、多因子绑定风控、AOP统一校验以及二级缓存同步机制,在实践中可通过模拟攻击场景验证防护效果,并结合自身系统特点进行适配改造。

16,550

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Creator Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧