工程含有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的用法的更多相关文章

  1. 机房收费系统之【只允许一个MDI窗体 错误:426】 标签: vb 2014-08-15 10:36 1149人阅读 评论(23)

    机房收费系统的主窗体是MDI窗体,为了在这个窗体上添加控件,所以我们在窗体上添加了picture控件,在MDI窗体中,子窗体实际上位于MDIClient里,即子窗体的父窗体就是MDIClient,而放 ...

  2. 使用DevExpress.XtraTabbedMdi.XtraTabbedMdiManager控件来加载MDI窗体

    使用DevExpress.XtraTabbedMdi.XtraTabbedMdiManager控件来加载MDI窗体     [csharp] view plaincopyprint? <SPAN ...

  3. Winform MDI窗体切换不闪烁的解决办法(测试通过)

    https://stackoverflow.com/questions/5817632/beginupdate-endupdate-for-datagridview-request SuspendLa ...

  4. 小菜学习Winform(四)MDI窗体(附示例)

    前言 在做winfrom项目的时候我们可能会用到嵌套窗体,就是说一个容器中有多个窗体,可以分别管理和应用这些窗体,.net中提供了一种机制就是MDI,可能大家都会用,这边就简单的介绍下. 简单应用 w ...

  5. MDI窗体

    1.设置父窗体 使用MDI窗体,需要先将父窗体的IsMdiContainer属性设置为True 2.生成用于MDI子窗体的窗体 1 frmTemp f1 = new frmTemp(); f1.Tex ...

  6. MDI窗体 的再度思考

    早在敲学生管理系统的时候,青山师哥就跟我说过  MDI 窗体 跟 子窗体的事情,当时只是简单的查询.小小的用了一下,没有太在意. 当再次面对着这个东西更深层的时候才想起师哥那句话.“好好研究一下这个东 ...

  7. C#解决MDI窗体闪屏的方法

    最近从师兄手上接了一个C#的项目,需要用到MDI窗体,可是每当我显示子窗体的时候会有一次“闪烁”,很明显,看起来非常不爽,查找许久,知道是每次在show()子窗体的时候都会调用子窗体构造函数重绘窗体, ...

  8. WPF实现MDI窗体的方法

    原文:WPF实现MDI窗体的方法 第一:新建一个类(Class) Win32Native.cs 代码如下: using System;  using System.Collections.Generi ...

  9. 2015.12.14 MDI(多文档窗口结构)设置基本解决,折腾一天,部分解决存在已久的问题。但效果仍不如临时航线的MDI窗体结构。

    创建从一个窗口弹出多个子窗口的结构叫MDI窗体结构 如果不按MDI结构管理,最简单的做法是: 在窗体A上添加菜单或按钮,在菜单或按钮事件中添加弹出B窗体代码: B b = new B(); b.sho ...

随机推荐

  1. bitcoin-qt忘记密码

    客户端有钱包加密功能,输入密码可以增强安全性. 但是,如果你把钱包文件弄丢了,那即使设了密码,币也会丢. 关闭bitcoin-qt,把钱包文件wallet.dat 剪到其他地方(但不要删除),然后重新 ...

  2. 2017.3.31 spring mvc教程(二)核心流程及配置详解

    学习的博客:http://elf8848.iteye.com/blog/875830/ 我项目中所用的版本:4.2.0.博客的时间比较早,11年的,学习的是Spring3 MVC.不知道版本上有没有变 ...

  3. Ubuntu使用日志2(在Eclipse中搭建C++交叉编译环境)

    Release用交叉编译:arm-none-linux-gnueabi-gcc. 搭建步骤: 1).在Project->Properties->C/C++ Build->Settin ...

  4. Nginx限制连接和请求

    一.ngx_http_limit_conn_module对同一个ip/server的连接数做限制.配置指令:limit_conn_zone语法: limit_conn_zone $variable z ...

  5. Ant Design Mobile 使用 rc-form

    引入: import { createForm } from 'rc-form'; 步骤一:绑定 form // 将form表单的api绑定到props,便于调用 const EditHeaderWr ...

  6. v-if 条件渲染分组

    因为 v-if 是一个指令,所以必须将它添加到一个元素上.但是如果想切换多个元素呢?此时可以把一个 <template> 元素当做不可见的包裹元素,并在上面使用 v-if.最终的渲染结果将 ...

  7. VM里面的桥接

      今天我们谈一谈桥接模式,一般的时候,我用的是NAT模式,需要设置另一个虚拟网卡的IP地址,而不是借助本机的物理网卡.   编辑---虚拟网络编辑器 有些时候直接设置桥接到某个网卡可能会不成功,我们 ...

  8. sqlserver 中EXEC和sp_executesql使用介绍

    sqlserver 中EXEC和sp_executesql使用介绍 MSSQL为我们提供了两种动态运行SQL语句的命令,各自是EXEC和sp_executesql;通常,sp_executesql则更 ...

  9. 娓娓道来c指针 (2)内存分配

    (2)内存分配 c语言中描写叙述变量的时候经常使用的两个用语 1.作用域:也叫可见域,指的是变量的作用范围. 在哪个范围内.该变量是可见的.能够使用的. 2.生存期:也叫存储期.指的是变量从创建到销毁 ...

  10. html禁止图片拖拽移动在新窗口打开

    一直觉得直接从网站的表格上复制数据挺方便的, 今天,领导突然说网站上的图片可以被别人拖走了,必须禁止,哎,果然只有领导才考虑得到这种事情啊 so, 将ondragstart="return ...