Windows 对话框
  顾名思义,对话框是应用程序创建的一个窗口,给出用户一些信息或者接收用户的输入。Delphi 中没有创建对话框的 模板(除了通用的对话框如打开对话框、字体对话框、颜色对话框等)。Delphi 本身使用 TForm 创建对话框。对话框可以使得临时输入的窗口创建 更加容易。不用 CreateWindow( ) 创建一个弹出窗口然后在上面添加控件,你只要制作一个资源模板,然后调用 DialogBox 就可以 了。本例中我们创建并使用资源模板,然后调用 Windows DialogBox( ) 函数。你可以参考 Win32 API 帮助的 “Dialog Boxes”部分。在程序示例里我使用 DialogBox( ) 创建了一个模式对话框。你需要为它准备好一个对话框资源文件 “Dlg1.RES”。 


对话框资源的创建
  你需要使用 brcc32.exe 编译对话框资源。这在 Delphi 帮助文档中没有详细说明。下面我们开始创建一个非常简单的对话框资源 .RC 文件。

First DIALOG  12, 10, 206, 86
     STYLE WS_POPUP | WS_DLGFRAME | WS_CAPTION
     CAPTION " A Dialog Form"
     FONT 10, "MS Sans Serif"
     {
     LTEXT "Simple Dialog"  200, 8, 6, 196, 8
     PUSHBUTTON "OK"   IDOK, 48, 71,  32, 12
     }

  这是 C 语言代码,不是 Pascal 代码。第一个“First”是资源名字,就像下面一行的“MyIcon”。

MyIcon  ICON  Floppy.ico

对于 .RC 文件内的图标,DIALOG 是一种资源,12、10、206、86 是对话框的标准的上、左、宽、高参数(单位不是像素,对话框单位参 见 Win32 API 帮助的“GetDialogBaseUnits”)。上和左与它的父窗体的上和左相关,以父窗体为参考原点。接下里来 是:STYLE WS_POPUP | WS_DLGFRAME | WS_CAPTION ,这些设置了对话框窗体的创建风格( C 语言中 的 | 和 Pascal 语言中的 or 一样)。还有一些其他的对话框风格:

DS_LOCALEDIT -指定编辑框控件在对话框上 使用程序数据模块的内存。默认情况下,对话框上的编辑框控件是使用应用程序数据模块之外的内存的。如果没有使用这个标志,那么不要向编辑框发 送 EM_GETHANDLE 和 EM_SETHANDLE 消息,因为控件没有存储在程序的数据模块。

DS_MODALFRAME -创建一个模式对话框,对话框可以通过指定 WS_CAPTION 和 WS_SYSMENU 结合标题栏和系统菜单。

DS_NOIDLEMSG -禁止 Windows 或其它程序在对话框显示时向它的 owner 窗体发送 WM_ENTERIDLE 消息。

DS_SYSMODAL -创建一个系统的模式对话框。

如果你使用了 WS_CAPTION 风格,那么“CAPTION " A Dialog Form"”这行将在对话框标题上放上这个字符 串,“FONT 10, "MS Sans Serif"”将会设置对话框内所有控件字体和尺寸。{ 和 } 对应 Pascal 中 的 begin 和 end ,在 { } 之间你可以放置希望出现在对话框上的控件,PUSHBUTTON 是一个按钮,参数跟 在 PUSHBUTTON 之后,形式如:
PUSHBUTTON "Text on Control" IDNUMBER, Left, Top, Width, Height 后面的参数为对话框单位而不是像素。这里创建的对话框 206 单位宽、86 单位高、左侧距父窗体 12 单位、顶部距父窗体 10 单位,对话框 上有静态文本框和按钮两个控件。

其他对话框控件
  对话框控件的语法形式为:
controlName text, IDnumber, Left, Top, Width, Height, style, extended-style

DEFPUSHBUTTON "Cancel" IDCANCEL, 8, 67,  32, 12
LTEXT "Static Text Left aligned"  201, 5, 21, 196, 24
CTEXT "Static Text Centered"     202, 18, 12, 170, 8
ICON  "Icon" -1, 1,1,0,0
EDITTEXT 300, 9, 47, 180, 50, ES_MULTILINE, WS_EX_CLIENTEDGE
CHECKBOX "Check Box", 100, 10, 60, 69, 8
AUTOCHECKBOX "Auto CheckBox", 101, 140, 60, 61, 8
RADIOBUTTON "radio", 400, 8, 32, 64, 8
AUTORADIOBUTTON "needs WS_GROUP", 401, 8, 42, 64, 8, WS_GROUP
GROUPBOX "GroupBox", -1, 4,22,150,42
   
你可以通过放置控件类型名字参数创建大部分 Windows 控件,参见下文的“在对话框中包含常规控件”部分。

  使用 DialogBox(hInstance, lpTemplate, hWndParent, lpDialogFunc);
参 见程序代码的“procedure DoDialog”,你会发现它设置对话框使用的一些变量,然后调用 DialogBox( )。 lpTemplate 为资源名称的 PChar 类型,父窗体为 hForm1 ,lpDialogFunc 设置为对话框函数的地址(参见帮助中 的 DialogProc 部分)。这个 DialogProc 类似于 WndProc ,用于获取对话框消息,参见代码中 的 DialogProc 。 WM_INITDIALOG 消息被发送后对话框就被创建了,因此你可以在这里设置控件。由于对话框是从模板创建的,所以 控件的句柄还不知道,这样可以用 ID 号码访问它们。通过 GetDlgItem(hWnd,IDNUMBER) 获取控件的句柄,你可以使用大量控件 的 SendMessage 或者状态变化(Enable( ) 等)。有几个特定的对话框函数根据 ID 编号直接使用 (SendDlgItemMessage、 CheckDlgButton、 SetDlgItemText、 GetDlgItemText)。 在 WM_COMMAND 消息中,LOWORD(wParam) 就是控件的 ID 号码。


有待完善…… 


对于本文的对话框演示程序,使用的“Dlg1.rc”源文件代码如下:

Z1 ICON Done2.ICO
Z2 ICON Flop.ICO

First DIALOG  12, 10, 206, 86
     STYLE WS_POPUP | WS_DLGFRAME | WS_CAPTION | WS_SYSMENU
     CAPTION " A Dialog Form"
     FONT 10, "MS Sans Serif"
     {
     CTEXT "Dialogs are really NON Delphi" 200, 18, 1, 170, 10
     ICON  "Z1" -1, 1,1,0,0
     ICON  "Z2" -1, 189,1,0,0
     CTEXT "Checkbox was Unchecked"     201, 18, 12, 170, 8
     LTEXT " "  202, 5, 21, 196, 24
     EDITTEXT      300, 14, 47, 100, 10
     AUTOCHECKBOX "Show MessageBox", 100, 10, 60, 69, 8
     AUTOCHECKBOX "Check me", 101, 140, 60, 61, 8
     DEFPUSHBUTTON "OK"   IDOK, 48, 71,  32, 12, WS_GROUP
     PUSHBUTTON "set Edit Text"   401, 108, 71,  44, 12,
     }
 
  使用 brcc32.exe 编译 Dlg1.rc 文件,我不知道为什么可以不使用“ #include <windows.h>”,但是确实通过编译了(生成 Dlg1.RES 文件)。

对话框程序
  本程序演示了创建与使用 Windows 对话框的方法,你需要使用上面代码编译得到的 Dlg1.RES 文件。  

program Dialogs;

uses
  Windows, Messages, smallUtils;
{$R *.RES}
{$R Dlg1.RES}
var
  wClass: TWndClass;
  hForm1, hExitBut, hDlgBut, hCheckCB, hEdit1,
  hLabel1, Font1, hLabel2, hLabel3: THandle;
  mainMsg: TMSG;
  Rect1: TRect;
  DlgText, DlgEditText: String;
  DlgChk, Dlg2Chk: Boolean;

function DialogProc(hWnd,Msg,wParam,lParam:Longint):Boolean; stdcall;
{这里处理对话框消息。有些消息如 WndProc 消息(WM_COMMAND、WM_CLOSE)列
在这里,有些消息(WM_INITDIALOG)没有列出。在对话框 Proc 经常使用
 DlgItem ID 而不是 hWnd }
var
  OKrect:TRect;
begin
  Result := False;
  case Msg of
WM_INITDIALOG: begin
                 {WM_INITDIALOG 是设置你的 Dlg Items 属性的地方,有些特定的
                 DlgItem 函数(SendDlgItemMessage、SetDlgItemText)
                 对此比较有用。}
                 DlgEditText := '';
                 SendMessage(hWnd, WM_SETICON, 1, LoadIcon(hInstance,'Z1'));
                 {对话框默认使用图标,你需要设置图标}
                 SendDlgItemMessage(hWnd,200,WM_SETFONT,Font1, 0);
                 {SendDlgItemMessage 使用 ID 编号代替 hWnd}
                 CheckDlgButton(hWnd,100,BST_CHECKED);
                 if SendMessage(hCheckCB,BM_GETCHECK,0,0) = BST_CHECKED then
                 begin
                   {你可以从主窗体获取信息来设置对话框}
                   SetWindowText(GetDlgItem(hWnd,201),'多选按钮被勾选');
                   {这里可以使用 SetWindowText,但是一样可以使用 SetDlgItemText。
                   SetDlgItemText(hWnd,201,'检查框被勾选');}
                   EnableWindow(GetDlgItem(hWnd,101),False);
                   {大部分改变窗口的函数对于对话框一样有效}
                 end;
                 {SetWindowText(GetDlgItem(hWnd,202),PChar(DlgText));}
                 SetDlgItemText(hWnd,202,PChar(DlgText));
                 SetDlgItemText(hWnd,300,PChar(GetWindowStr(hEdit1)));
                 GetWindowRect(GetDlgItem(hWnd,IDOK),OKrect);
                 SetCursorPos(OKrect.Left+10,OKrect.Top+10);
               end;
WM_COMMAND: begin
              {和 MessageProc 的 WM_COMMAND 消息不一样,wParam 与 LParam
              有不同的用途。}
              if LOWORD(wParam) = IDOK then
              begin
                {对话框在 LOWORD(wParam) 使用 DlgItem ID}
                if (IsDlgButtonChecked(hWnd,101) = BST_CHECKED)
                then  Dlg2Chk := True;
                if (IsDlgButtonChecked(hWnd,100) = BST_CHECKED) then
                begin
                  MessageBox(hWnd,'对话框上多选按钮被勾选',
                    '退出对话框',MB_OK or MB_ICONQUESTION);
                  DlgChk := True;
                end;
                DlgEditText := GetWindowStr(GetDlgItem(hWnd,300));
                EndDialog(hWnd,1);
                Result := True;
              end
              else if LOWORD(wParam) = 401
                   then SetDlgItemText(hWnd,300, '新的编辑框文本')
                   else if LOWORD(wParam) = 101
                        then  MessageBox(hWnd,'对话框上多选按钮被单击',
                                  '单击它',MB_OK or MB_ICONQUESTION);
            end;
WM_CLOSE: begin
            {和 MessageProc 不一样,你需要使用 EndDialog 退出一个对话框}
            EndDialog(hWnd,1);
            Result := True;
          end;
  end;
end;

procedure DoDialog;
var
  Dsize: TdriveSize;
begin
  if hLabel3 <> 0 then
  begin
    DestroyWindow(hLabel3);
    while PeekMessage(mainMsg, 0, 0, 0, PM_REMOVE)
    do  DispatchMessage(mainMsg);
    hLabel3 := 0;
  end;
  Dsize := DiskSpace('C:\');
  DlgText := 'C 盘总容量为  '+Int2Str(Dsize.TotalS)+
           ' 字节 - 可用空间为  '+ Int2Str(Dsize.FreeS);
  {DlgText 被用于对话框的静态标签控件,你应该在调用 DialogBox( ) 前设置好对话框
  需要的所有的变量。}
  DialogBox(hInstance, 'First', hForm1, @DialogProc);
  {DialogBox 将根据资源 DIALOG 的 'First' 创建一个模式对话框,它以 hForm1 作为
  父窗体,以 DialogProc 作为 WndProc (MessageProc)}
  {可以从对话框获取返回值}
  if DlgChk then
  MessageBox(hForm1,'这里 DlgChk = True',
      '对话框返回值',MB_OK or MB_ICONQUESTION);
  if Dlg2Chk then
  begin
    hLabel3 := CreateWindow('Static', '"Check me" 多选按钮被勾选',
         WS_VISIBLE or WS_CHILD or SS_CENTER,6,200,370,29,hForm1,0,hInstance,nil);
    SendMessage(hLabel3, WM_SETFONT, Font1,0);
  end;
  SetWindowText(hLabel2,@DlgEditText[1]);
  DlgChk := False;
  Dlg2Chk := False;
end;

function MessageProc(hWnd,Msg,wParam,lParam:Integer):Integer; stdcall;
begin
  case Msg of
    WM_COMMAND: if lParam = abs(hExitBut)
                then PostMessage(hForm1,WM_CLOSE,0,0)
                else if (LParam = abs(hDlgBut))
                     then DoDialog;
    WM_DESTROY: PostQuitMessage(0);
  end; // case 语句结束
  Result := DefWindowProc(hWnd,Msg,wParam,lParam);
end;

begin     // 主程序开始 //
  DlgChk := False;
  Dlg2Chk := False;
  hLabel3 := 0;

  Font1 := CreateFont(-16,0,0,0,FW_BOLD,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,
   CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,VARIABLE_PITCH or FF_SWISS,'Arial');

  wClass.hInstance := hInstance;
  with wClass do
  begin
    style :=        CS_PARENTDC or CS_BYTEALIGNWINDOW;
    hIcon :=        LoadIcon(hInstance,'MAINICON');
    lpfnWndProc :=  @MessageProc;
    hbrBackground:= COLOR_BTNFACE+1;
    lpszClassName:= 'Form Class';
    hCursor :=      LoadCursor(0,IDC_ARROW);
  end;
  RegisterClass(wClass);

  SetRect(Rect1,0,0,430,300);
  if not AdjustWindowRect(Rect1,WS_CAPTION or WS_MINIMIZEBOX or WS_SYSMENU,False)
  then SetRect(Rect1,0,0,438,328);

  hForm1 := CreateWindow(wClass.lpszClassName, '对话框演示程序',
    WS_CAPTION or WS_MINIMIZEBOX or WS_SYSMENU or WS_VISIBLE,
    (GetSystemMetrics(SM_CXSCREEN) div 2)-200,
    (GetSystemMetrics(SM_CYSCREEN) div 2)-160,
    Rect1.Right-Rect1.Left, Rect1.Bottom-Rect1.Top,
    0, 0, hInstance, nil);

  hLabel1 := CreateWindow('Static', '对话框演示',
         WS_VISIBLE or WS_CHILD or SS_CENTER,8,8,388,22,hForm1,0,hInstance,nil);
  SendMessage(hLabel1,WM_SETFONT,Font1,0);

  hLabel2 := CreateWindow('Static',
         '在下面输入你想放置到对话框的文字'#10'对话框编辑框如数的文字将在此显示',
         WS_VISIBLE or WS_CHILD or SS_LEFT,10,38,290,28,hForm1,0,hInstance,nil);
  SendMessage(hLabel2,WM_SETFONT,GetStockObject(ANSI_VAR_FONT),0);

  hExitBut := CreateWindow('Button','退 出',
    WS_VISIBLE or WS_CHILD or BS_PUSHBUTTON or BS_TEXT,
    350,270,74,24, hForm1,0, hInstance,nil);

  hEdit1 := CreateWindowEx(WS_EX_CLIENTEDGE,'Edit','这里输入的文字将显示在对话框中',
    WS_VISIBLE or WS_CHILD or ES_LEFT or ES_AUTOHSCROLL,
    16,78,410,21,hForm1,0,hInstance,nil);
  SendMessage(hEdit1,WM_SETFONT,GetStockObject(ANSI_VAR_FONT),0);

  hDlgBut := CreateWindow('Button','显示对话框',
    WS_VISIBLE or WS_CHILD or BS_PUSHBUTTON or BS_TEXT,
    30,160,144,24, hForm1,0, hInstance,nil);
  SendMessage(hDlgBut, WM_SETFONT, GetStockObject(ANSI_VAR_FONT),0);

  hCheckCB := CreateWindow('Button','对话框多选检测按钮',
    WS_CHILD or BS_AUTOCHECKBOX or WS_VISIBLE,
    20,130,190,24, hForm1,0,hInstance,nil);
  SendMessage(hCheckCB, WM_SETFONT, GetStockObject(ANSI_VAR_FONT),0);

  while GetMessage(mainMsg,0,0,0) do
  begin
    TranslateMessage(mainMsg);
    DispatchMessage(mainMsg);
  end;
  DeleteObject(Font1);
  DlgText := '';
  DlgEditText := '';
end.

 

在对话框中包含常规控件
  为了在对话框里创建预定义的控件类,可以使用如下的一般语法,参数为:

ClassName text, IDnumber, x, y, width, height , style , extended-style
 X 和 width 是水平方向单位,是对话框基本宽度单位的 1/4 ,Y 和 height 是竖直方向单位,是对话框基本高度单位的 1 /8 。当前对话框基本单位是计算机从当前系统字体的高度和宽度得到的,GetDialogBaseUnits( ) 函数可以返回对话框基本单位的对应 像素值。

ControlName - 预定义的控件的类名,比如 BUTTON、 COMBOBOX、 EDIT、 LISTBOX、 SCROLLBAR、 STATIC 等。

text - 指 定控件上显示的文本。文本位置在控件指定尺寸之内或者接近控件。这个参数是有双引号(")括起来的 0 到多个字符。字符串自动以零结束并在资源文件返回 结果中转换成 Unicode 字符。默认情况下,双引号括起的字符是 ANSI 字符,交换码顺序被认为是按位交换码顺序。如果字符串加上 L 前缀, 字符串被认为是宽字符组成,交换码顺序被认为是两位交换码,这就是 Unicode 字符。如果双引号本身在文本内,那么需要连续使用双引号两次。 And 符号(&)放在文本中表示后面跟着的字符是控件的助记符(加速字符),当控件显示的时候,& 不会出现,后面的字符会自动加上下 划线显示,用户可以通过按下下划线助记符来选择这个控件。为了在字符串中使用 & 字符,你需要连续两次使用(&&)。

IDnumber - 指定控件标识。这个值为 Word 类型,介于 0 到 65,535 之间。

x - 给出控件在对话框客户区域左边距,这个值为 Word 类型,介于 0 到 65,535 之间。这个坐标轴在对话框的客户区域的左边缘为 0 对话框单位。

y - 给出控件在对话框客户区域上边距,这个值为 Word 类型,介于 0 到 65,535 之间。这个坐标轴在对话框的客户区域的上边缘为 0 对话框单位。

width - 指 定控件宽度,这个值为 Word 类型,介于 1 到 65,535 之间。宽度单位为 1/4 字符。 Specifies the width of the control. This value must be a Word value in the range 1 through 65,535. The width is in 1/4-character units. 
height - 指定控件高度,这个值为 Word 类型,介于 1 到 65,535 之间。宽度单位为 1/8 字符。 

style - 指定控件的风格。利用逻辑或操作( | )组合多个风格。 

extended-style - 指定扩展风格(WS_EX_xxx)。你必须给定一种风格以便使用扩展风格
Posted on 2008-10-03 21:55 micheal's tech 阅读(1886) 评论(0)  编辑 收藏 引用 所属分类: visual c++

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理