网络编程 | 站长之家 | 网页制作 | 图形图象 | 操作系统 | 冲浪宝典 | 软件教学 | 网络办公 | 邮件系统 | 网络安全 | 认证考试 | 系统进程
Firefox | IE | Maxthon | 迅雷 | 电驴 | BitComet | FlashGet | QQ | QQ空间 | Vista | 输入法 | Ghost | Word | Excel | wps | Powerpoint
asp | .net | php | jsp | Sql | c# | Ajax | xml | Dreamweaver | FrontPages | Javascript | css | photoshop | fireworks | Flash | Cad | Discuz!
当前位置 > 网站建设学院 > 网络编程 > Delphi
Tag:注入,存储过程,分页,安全,优化,xmlhttp,fso,jmail,application,session,防盗链,stream,无组件,组件,md5,乱码,缓存,加密,验证码,算法,cookies,ubb,正则表达式,水印,索引,日志,压缩,base64,url重写,上传,控件,Web.config,JDBC,函数,内存,PDF,迁移,结构,破解,编译,配置,进程,分词,IIS,Apache,Tomcat,phpmyadmin,Gzip,触发器,socket
网络编程:ASP教程,ASP.NET教程,PHP教程,JSP教程,C#教程,数据库,XML教程,Ajax,Java,Perl,Shell,VB教程,Delphi,C/C++教程,软件工程,J2EE/J2ME,移动开发
本月文章推荐
.解决无法按y轴显示的问题!.
.Format的用法.
.走近Inprise/Borland.
.用Delphi实现远程屏幕抓取.
.浅谈引用计数.
.控件在运行状态改变大小.
.borland工程师如何保证父类(TStr.
.使用DLL文件中封装的窗口.
.进程、窗口句柄、文件属性、程序.
.使用内存映象实现进程间全局变量.
.Delphi中的线程类--之(5,大结局.
.DELPHI中的消息处理机制.
.如何在启动机器时自动运行adsl拨.
.Delphi制作带图标的弹出式选单.
.如何用编程实现TDateTimePicker的.
.在Delphi中如何控制其它应用程序.
.Delphi编写组件封装asp代码的基本.
.三层数据库与应用程序服务器的小.
.Kylix预览.
.对Delphi控件的一点改良(二).

Delphi中实现可以更改大小的对话框

发表日期:2006-2-4


 

关键字:Dialog、对话框、resizable

1、问题的提出
问题来自Stanley_Xu,希望得到只有关闭按钮(还可以有帮助),左上也没有程序的图标并且能够更改窗口大小的对话框。
VCL中为TForm设置了BorderStyle和BorderIcons属性,用以简化窗口样式的设置(否则就要调用SetWindowLong和GetWindowLong等API函数)。TFormBorderStyle和TBorderIcon的定义和说明如下:

Value          Meaning
bsDialog       Not resizable; standard dialog box border//不能改大小
bsSingle       Not resizable; single-line border
bsNone Not     resizable; no visible border line
bsSizeable     Standard resizable border
bsToolWindow   like bsSingle but with a smaller caption
bsSizeToolWin  like bsSizeable with a smaller caption

type TBorderIcon = (biSystemMenu, biMinimize, biMaximize, biHelp);
TBorderIcons = set of TBorderIcon;

Value          Meaning
biSystemMenu   The form has a Control menu (also known as a System menu).
biMinimize     The form has a Minimize button
biMaximize     The form has a Maximize button
biHelp         If BorderStyle is bsDialog or biMinimize and biMaximize are excluded, a question mark appears in the form's title bar and when clicked, the cursor changes to crHelp; otherwise,no question mark appears.

显然,通过BorderStyle和BorderIcons只能够满足一般的需要,要实现能够修改大小的对话框就有所力不能及了。
一般情况下,我要得到不能最大最小化但又可以更改大小的窗口,就把BorderStyle设置为bsSizeable,把BorderIcons的biMinimize和biMaximize去掉,结果象这样:窗口可以修改大小,但左上角有图标,:

VcLSizableDlg
图 1 带图标的对话框


注意左上角有图标。

而我们的目标则是下面的两种效果,左上角都没有图标,但窗口都可以修改大小。

OpenSaveDlg
图 2 打开文件对话框

Browse4Folder

图 3浏览文件夹对话框


2、问题解决一半
搜索了一下MSDN,找到一篇教你如何设计可以可更改大小的属性页的文章(在MFC中CPropertySheet是作为CPropertyPage子页出现的,后者从CDialog继承而来,通常不能修改大小)《
How To Design a Resizable MFC Property Sheet》,文中介绍的方法是在属性页创建之前修改窗口样式,然后手动处理WM_SIZE消息。

int CALLBACK CMyPropertySheet::XmnPropSheetCallback(HWND hWnd, UINT message, LPARAM lParam)
{
    extern int CALLBACK AfxPropSheetCallback(HWND, UINT message, LPARAM lParam);
    // XMN: Call MFC's callback
    int nRes = AfxPropSheetCallback(hWnd, message, lParam);

    switch (message)
    {
    case PSCB_PRECREATE:
       
// Set our own window styles
        ((LPDLGTEMPLATE)lParam)->style |= (DS_3DLOOK | DS_SETFONT
  | WS_THICKFRAME | WS_SYSMENU | WS_POPUP | WS_VISIBLE | WS_CAPTION);
        break;
    }
    return nRes;
}

我试着将同样的方法用到VCL的一个Form中。在设计时把BorderStyle设置为bsDialog,然后重载CreateParams方法。但结果是对话框确实变成了厚边框(因为有WS_THICKFRAME样式),鼠标移动到各个边框后能够自动变化,左上角也没有图标,但窗口就是不能改变大小(添加的WM_SIZE消息处理过程没有触发)。问题出在哪里呢?

HalfZoCDlgResizable

图 4 还不能完全令人满意的对话框

3、问题的解决
查了一翻Forms.pas的源代码,发现了问题所在。TCustomForm的WM_NCCREATE消息处理过程中有一个ModifySystemMenu嵌入过程,用来修改Form的系统菜单。注意下面红色文字说的是“使系统菜单看起来像对话框一样”。接下来的几句代码就把系统菜单项删得只剩下了“移动”和“关闭”。

procedure TCustomForm.WMNCCreate(var Message: TWMNCCreate);

procedure ModifySystemMenu;
var
    SysMenu: HMENU;
begin
    ……
   
{ Modify the system menu to look more like it's s'pose to }
    SysMenu := GetSystemMenu(Handle, False);
    if FBorderStyle = bsDialog then
    begin
        
{ Make the system menu look like a dialog which has only
        Move and Close }

        DeleteMenu(SysMenu, SC_TASKLIST, MF_BYCOMMAND);
        DeleteMenu(SysMenu, 7, MF_BYPOSITION);
        DeleteMenu(SysMenu, 5, MF_BYPOSITION);
        DeleteMenu(SysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
        DeleteMenu(SysMenu, SC_MINIMIZE, MF_BYCOMMAND);
        DeleteMenu(SysMenu, SC_SIZE, MF_BYCOMMAND);
        DeleteMenu(SysMenu, SC_RESTORE, MF_BYCOMMAND);
    end else
    ……
end;

begin
    inherited;
    SetMenu(FMenu);
    if not (csDesigning in ComponentState) then ModifySystemMenu;
end;

所以,问题出在由于“SC_SIZE”被删掉,窗口的样式出现了畸形:有WS_THICKFRAME(可以修改窗口大小),但不响应WM_SIZE消息(SC_SIZE被删掉)。
解决的办法很简单:实现自己的WM_NCCREATE消息处理过程,手动修改系统菜单。


procedure TZoCDlgResizable.WMNCCreate(var Message: TWMNCCreate);

 //The following codes are copied from Form.pas line 4047, Delphi 7 sp1.
 procedure ModifySystemMenu;
 var
     SysMenu   : HMENU;
 begin
     SysMenu := GetSystemMenu(Handle, False);
     
{ Make the system menu look like a dialog which has only
  Move, Size and Close commands}
     DeleteMenu(SysMenu, SC_TASKLIST, MF_BYCOMMAND);
     DeleteMenu(SysMenu, 7, MF_BYPOSITION);
     
//Don't remove the separater before CLOSE command.
//   DeleteMenu(SysMenu, 5, MF_BYPOSITION);

     DeleteMenu(SysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
     DeleteMenu(SysMenu, SC_MINIMIZE, MF_BYCOMMAND);
     
{ Don't remove the SIZE command, otherwise we'll lose the
  capability of resizing the Dialog. }
//   DeleteMenu(SysMenu, SC_SIZE, MF_BYCOMMAND);

     DeleteMenu(SysMenu, SC_RESTORE, MF_BYCOMMAND);
 end;

begin
   
{ Skip TCustomForm's WM_NCCREATE handler, which remove
    the SIZE command from the System Menu.}
    inherited DefaultHandler(Message);
   
//Dealing with the System Menu in our own way.
    ModifySystemMenu;
end;

4、TZoCDlgResizable类
最终的解决方案我封装为一个继承自TForm的类,效果如下,与图1相同(如果想要图2那样的系统菜单则把调用ModifySystemMenu的行删掉),使用的时候从TZoCDlgResizable继承一个即可。
BTW:我还顺手给TZoCDlgResizable加了个SizeGrip属性,具体情况可以看代码。


图 5 没有图标、可以修改大小、带有SizeGrip的对话框

下载(exe和源代码)
http://www.zocsoft.com/temp/Resizable_Dialog.rar

5、参考资料:

MSDN: How To Design a Resizable MFC Property Sheet

引用地址:《Delphi中实现可以更改大小的对话框


上一篇:如何在delphi5中实现对word文档页眉的设置? 人气:4710
下一篇:QQ窗体自动隐藏效果探究 人气:3975
浏览全部Delphi的内容 Dreamweaver插件下载 网页广告代码 祝你圣诞节快乐 2009年新年快乐