给MDI窗体加背景,解释MakeObjectInstance和CallWindowProc的用法
工程含有1个MDI主窗口和2个子窗口。唯一需要注意的是,每个窗体都有ClientHandle,但只有当自己是MDI主窗体的情况下才有值,否则等于0。
unit Unit1; interface uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls, jpeg, Menus; type
TForm1 = class(TForm)
Image1: TImage;
MainMenu1: TMainMenu;
N1: TMenuItem;
dd1: TMenuItem;
procedure FormShow(Sender: TObject);
private
FClientInstance : TFarProc;
FPrevClientProc : TFarProc;
Procedure ClientWndProc(Var Message: TMessage); // 自定义的窗口过程
{ Private declarations }
public
{ Public declarations }
end; var
Form1: TForm1; implementation {$R *.DFM}
procedure TForm1.ClientWndProc(var Message: TMessage);
var
Dc : hDC;
Row : Integer;
Col : Integer;
begin
with Message do
case Msg of
WM_ERASEBKGND:// 当要重会背景时
begin
Dc := TWMEraseBkGnd(Message).DC; // 消息自带DC
// 铺图象
// 计算并会制行和高总共要画的数量。
for Row := to ClientHeight div Image1.Picture.Height do
for Col := to ClientWidth div Image1.Picture.Width do
BitBlt(Dc,Col * Image1.Picture.Width, Row * Image1.Picture.Height
,Image1.Picture.Width, Image1.Picture.Height
,Image1.Picture.Bitmap.Canvas.Handle, , , SRCCOPY);
Result := ; // 到此结束,并不继续传递
end;
else // 传递其他消息
Result := CallWindowProc(FPrevClientProc,ClientHandle,Msg,wParam,lParam);
end;
end;
procedure TForm1.FormShow(Sender: TObject);
begin
FClientInstance := MakeObjectInstance(ClientWndProc);//将自定义过程的地址入口存入PClientInstance中
FPrevClientProc := Pointer(GetWindowLong(ClientHandle, GWL_WNDPROC));//记录消息位置
SetWindowLong(ClientHandle,GWL_WNDPROC,LongInt(FClientInstance));//重新载入窗口的消息并继续处理。
end; end.
另外还有: Delphi非应用程序主窗口创建MDI (把原来的主窗体都给换掉了并且关闭掉了,牛!)
http://blog.csdn.net/suiyunonghen/article/details/4209306
另一个通过修改窗口函数达到目的的例子(禁止用键盘左右箭头,去切换PageControl页签):
unit Unit1; interface uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls; type
TForm1 = class(TForm)
PageControl1: TPageControl;
TabSheet1: TTabSheet;
TabSheet2: TTabSheet;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
procedure EditWndProc(var Message: TMessage);
public
{ Public declarations }
end; var
Form1: TForm1;
EditHandle: THandle;
EditPointer:Pointer; implementation {$R *.dfm} procedure TForm1.EditWndProc(var Message: TMessage);
begin
case Message.Msg of
WM_KEYDOWN : //如果是按键消息
begin
if Message.WParam in [,] then //如果是左右箭头
Exit;
end;
end;
Message.Result:=CallWindowProc(EditPointer, EditHandle, Message.Msg, Message.WParam, Message.LParam);
end; procedure TForm1.FormCreate(Sender: TObject);
Var P:Pointer;
begin
EditHandle:=PageControl1.Handle;
if EditHandle<> then
begin
EditPointer := Pointer(GetWindowLong(EditHandle, GWL_WNDPROC));
P := Classes.MakeObjectInstance(EditWndProc);
SetWindowLong(EditHandle, GWL_WNDPROC, Longint(P));
end;
end;
我的理解:不能通过覆盖TPageControl的WndProc来达到目的,否则WndProc这个函数写在哪里呢(因为我没有重新定义一个类)?只能通过替换TPageControl的WndProc来达到目的。
给MDI窗体加背景,解释MakeObjectInstance和CallWindowProc的用法的更多相关文章
- 机房收费系统之【只允许一个MDI窗体 错误:426】 标签: vb 2014-08-15 10:36 1149人阅读 评论(23)
机房收费系统的主窗体是MDI窗体,为了在这个窗体上添加控件,所以我们在窗体上添加了picture控件,在MDI窗体中,子窗体实际上位于MDIClient里,即子窗体的父窗体就是MDIClient,而放 ...
- 使用DevExpress.XtraTabbedMdi.XtraTabbedMdiManager控件来加载MDI窗体
使用DevExpress.XtraTabbedMdi.XtraTabbedMdiManager控件来加载MDI窗体 [csharp] view plaincopyprint? <SPAN ...
- Winform MDI窗体切换不闪烁的解决办法(测试通过)
https://stackoverflow.com/questions/5817632/beginupdate-endupdate-for-datagridview-request SuspendLa ...
- 小菜学习Winform(四)MDI窗体(附示例)
前言 在做winfrom项目的时候我们可能会用到嵌套窗体,就是说一个容器中有多个窗体,可以分别管理和应用这些窗体,.net中提供了一种机制就是MDI,可能大家都会用,这边就简单的介绍下. 简单应用 w ...
- MDI窗体
1.设置父窗体 使用MDI窗体,需要先将父窗体的IsMdiContainer属性设置为True 2.生成用于MDI子窗体的窗体 1 frmTemp f1 = new frmTemp(); f1.Tex ...
- MDI窗体 的再度思考
早在敲学生管理系统的时候,青山师哥就跟我说过 MDI 窗体 跟 子窗体的事情,当时只是简单的查询.小小的用了一下,没有太在意. 当再次面对着这个东西更深层的时候才想起师哥那句话.“好好研究一下这个东 ...
- C#解决MDI窗体闪屏的方法
最近从师兄手上接了一个C#的项目,需要用到MDI窗体,可是每当我显示子窗体的时候会有一次“闪烁”,很明显,看起来非常不爽,查找许久,知道是每次在show()子窗体的时候都会调用子窗体构造函数重绘窗体, ...
- WPF实现MDI窗体的方法
原文:WPF实现MDI窗体的方法 第一:新建一个类(Class) Win32Native.cs 代码如下: using System; using System.Collections.Generi ...
- 2015.12.14 MDI(多文档窗口结构)设置基本解决,折腾一天,部分解决存在已久的问题。但效果仍不如临时航线的MDI窗体结构。
创建从一个窗口弹出多个子窗口的结构叫MDI窗体结构 如果不按MDI结构管理,最简单的做法是: 在窗体A上添加菜单或按钮,在菜单或按钮事件中添加弹出B窗体代码: B b = new B(); b.sho ...
随机推荐
- EffectiveJava(13)使类和成员的可访问性最小化
1.为什么要使类和成员可访问性最小化 它可以有效地解除组成系统的各模块之间的耦合关系,使得这些模块可以独立的开发 测试 优化 使用 理解和修改.提高软件的可重用性 2.成员的访问级别 私有(priva ...
- C++ 设置文件最近修改时间
利用VS开发C++项目,经常发现修改系统时间后,每次编译过程会变得很慢,其原因就是当你把系统时间调到未来的一个时间点,然后有意或者无意编辑过一些代码文件,那么这些文件的时间戳就停留在未来. 当你把系统 ...
- VS中c++文件调用c 函数 ,fatal error C1853 预编译头文件来自编译器的早期版本号,或者预编译头为 C++ 而在 C 中使用它(或相反)
出现错误:error C1853: "Debug\ConsoleApplication1.pch"预编译头文件来自编译器的早期版本号.或者预编译头为 C++ 而在 C 中使用它(或 ...
- redux VS mobx (装饰器配合使用)
前言:redux和mobx都是状态管理器,避免父级到子级再到子子级嵌套单向数据流,可以逻辑清晰的管理更新共享数据.(刷新页面redux储蓄数据即消失) 配置使用装饰器(使用高阶函数包装你的组件): n ...
- selenium从入门到应用 - 6,EventFiringWebDriver和监听器
本系列所有代码 https://github.com/zhangting85/simpleWebtest 本文将介绍一个Java+TestNG+Maven+Selenium的web自动化测试脚本环境下 ...
- 解决java.math.BigDecimal divide方法运算结果为无限小数问题
http://samueli.iteye.com/blog/224755 BigDecimal除法运算报错,错误如下:Non-terminating decimal expansion; no exa ...
- ajax读取文件内容
读取json文件 $.ajax({ url: 'manifest.webapp', type: 'GET', dataType: 'json',//类型不对会出错 timeout: 1000, //设 ...
- C#中执行存储过程并在SQL server中调试
1.编写存储过程 ) drop PROCEDURE [dbo].[sp_calcPci_of_baseRcd_GTmpTbl] CREATE PROCEDURE [dbo].[sp_calcPci_o ...
- 高抛低吸T+0操作要领(目前行情短线炒作的必备技能)
最近的行情只能用操蛋来形容,但是危机中不乏机会.现在已经不是之前行情的思路,那着一个股票长线抱着,即使是好的牛股,也经不起目前行情的这 么折腾.所以,现在最适合的操作方式就是高抛低吸.今天低吸保不准明 ...
- Shell计算器
#!/bin/bash # filename : jisuan.sh # description : add, subtract, multiply, and divide print_usage() ...