模式窗体和非模式窗体

模式窗体和非模式窗体
区别:模式窗体:你必须关闭该窗体,才能操作其它窗体;比如说,必须按确定或取消,或者按关闭。 非模式窗体:不必关闭该窗体,就可转换到其它窗体上进行操作。
模式窗体:ModalForm.Showmodal;  
非模式窗体:ModelessForm.Show;
TCustomForm是Windows窗口(一般窗口与对话框)的基类。它有两个显示窗口的方法:Show()和ShowModal()分别用来显示非模态与模态的窗口。不过,它对于模态窗口的实现并没有利用Windows系统提供的DialogBox()之类的API,而是VCL自己实现的。原因可能是无法将DialogBox()与VCL的Form机制很好地结合。
这一节来研究一下Show()和ShowModal()的具体实现。
先是Show():

None.gif procedure TCustomForm.Show;
None.gifbegin
None.gif  Visible :
=  True;
None.gif  BringToFront;
None.gifend;
None.gif


Show()的代码非常简单,而且易懂,它的行为与其名称一样的单纯。
而ShowModal()要做的事情则多得多:

None.gif function  TCustomForm.ShowModal:  Integer ;
None.gifvar
None.gif  …… 
//  省略变量声明
None.gifbegin
None.gif  …… 
//  省略部分代码
None.giftry
None.gif  Show; 
//  调用Show()方法显示窗口
None.gif  try
None.gif    SendMessage(Handle, CM_ACTIVATE, 
0 0 );
None.gif    ModalResult :
=   0 ;
None.gif    
//  接管线程主消息循环,使窗口“模态”化
None.gif    repeat
None.gif     Application.HandleMessage;
None.gif    
if  Application.FTerminate  then
None.gif      ModalResult :
=  mrCancel
None.gif    
else
None.gif    
if  ModalResult  <>   0   then  CloseModal;
None.gif    until ModalResult 
<>   0 ;
None.gif    Result :
=  ModalResult;
None.gif    SendMessage(Handle, CM_DEACTIVATE, 
0 0 );
None.gif    
if   Get  ActiveWindow  <> Handle  then
None.gif      ActiveWindow :
=   0 ;
None.gif   finally
None.gif     Hide; 
//  窗口消失
None.gif   
end ;
None.gif  finally
None.gif    
//  省略部分代码
None.gif  
end ;
None.gif
end ;
None.gif


可见,VCL中的模态窗口是通过接管线程主消息循环来实现的,只是它的退出循环条件是ModalResult <> 0(ModalResult初始值为0),那么,ModalResult的值是何时被改变的呢?有两种方式可以改变这个ModalResult的值:
一种是程序员在模态窗口中的某个事件代码中显式地改变ModalResult的值。如:
ModalResult := mrOK;
另一种是设置该窗口上的某个按钮的ModalResult的属性值,当单击该按钮后就改变了窗口的ModalResult。也许有人会奇怪,按钮属性是如何和窗口的属性联系起来的呢?看一下TButton的Click方法就知道了,该方法会在每个按钮被按下后被执行:
procedure TButton.Click;
var
Form: TCustomForm;
begin
// 获取按钮父窗口的TCustomForm对象
Form := GetParentForm(Self);
// 改变Form对象的ModalResult值
if Form <> nil then Form.ModalResult := ModalResult;
// 调用TControl.Click(),即调用OnClick事件的用户代码
inherited Click;
end;
按钮被按下后,这段程序会首先得到执行,最后的那行在对TControl.Click()的调用中,才会执行Delphi程序员为该按钮定义的OnClick事件的代码。
1.模式窗体
type
  TFormScroll = class(TForm)
var
  //声明一个窗体类型的变量
  FormScroll: TFormScroll;
begin
  // default value
  Result := Col;
  try
    FormScroll := TFormScroll.Create (Application);//创建窗体
    try
      // initialize the data
      FormScroll.SelectedColor := Col;
      // show the form 显示这个窗体
      if FormScroll.ShowModal = mrOK then
        Result := FormScroll.SelectedColor;
    finally
      FormScroll.Free;
    end;
  except
    on E: Exception do
      MessageDlg ('Error in FormDLL: ' +
        E.Message, mtError, [mbOK], 0);
  end;
end;
function TCustomForm.ShowModal: Integer;
var
  WindowList: Pointer;
  SaveFocusCount: Integer;
  SaveCursor: TCursor;
  SaveCount: Integer;
  ActiveWindow: HWnd;
begin
  CancelDrag;
  if Visible or not Enabled or (fsModal in FFormState) or
    (FormStyle = fsMDIChild) then
    raise EInvalidOperation.Create(SCannotShowModal);
  if GetCapture <> 0 then SendMessage(GetCapture, WM_CANCELMODE, 0, 0);
  ReleaseCapture;
  Include(FFormState, fsModal);
  ActiveWindow := GetActiveWindow;
  SaveFocusCount := FocusCount;
  Screen.FSaveFocusedList.Insert(0, Screen.FFocusedForm);
  Screen.FFocusedForm := Self;
  SaveCursor := Screen.Cursor;
  Screen.Cursor := crDefault;
  SaveCount := Screen.FCursorCount;
  WindowList := DisableTaskWindows(0);
  try
    Show;
    try
      SendMessage(Handle, CM_ACTIVATE, 0, 0);
      ModalResult := 0;
      repeat
        Application.HandleMessage;
        if Application.FTerminate then ModalResult := mrCancel else
          if ModalResult <> 0 then CloseModal;
      until ModalResult <> 0;
      Result := ModalResult;
      SendMessage(Handle, CM_DEACTIVATE, 0, 0);
      if GetActiveWindow <> Handle then ActiveWindow := 0;
    finally
      Hide;
    end;
  finally
    if Screen.FCursorCount = SaveCount then
      Screen.Cursor := SaveCursor
    else Screen.Cursor := crDefault;
    EnableTaskWindows(WindowList);
    if Screen.FSaveFocusedList.Count > 0 then
    begin
      Screen.FFocusedForm := Screen.FSaveFocusedList.First;
      Screen.FSaveFocusedList.Remove(Screen.FFocusedForm);
    end else Screen.FFocusedForm := nil;
    if ActiveWindow <> 0 then SetActiveWindow(ActiveWindow);
    FocusCount := SaveFocusCount;
    Exclude(FFormState, fsModal);
  end;
end;
2.非模式窗体
var
  FormScroll: TFormScroll;
begin
  FormScroll := TFormScroll.Create (Application);  //创建窗体
  try
    // initialize the data
    FormScroll.FormHandle := FormHandle;
    FormScroll.MsgBack := MsgBack;
    FormScroll.SelectedColor := Col;
    // show the form  显示非模式窗体
    FormScroll.Show;
  except
    on E: Exception do
    begin
      MessageDlg ('Error in FormDLL: ' +
        E.Message, mtError, [mbOK], 0);
      FormScroll.Free;
    end;
  end;
end;

procedure TCustomForm.Show;
begin
  Visible := True;
  BringToFront;
end;

转载于:https://www.cnblogs.com/sideandside/archive/2007/04/28/731279.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
program Hackdiy; uses Windows, Messages; var TheMessage: TMsg; const ClassName = 'MainForm_FOrm1'; // 过程回调函数 function FormProc(hForm, MsgID, WParam, LParam: LongWord): LongWord; stdcall; const {$J+} TempFont: DWORD = 0; {$J-} ControlID1 = 1; ControlID2 = 2; ControlID3 = 3; var EditText: array[0..30] of Char; begin Result := DefWindowProc(hForm, MsgID, WParam, LParam); // 标准处理 case MsgID of WM_CREATE: begin TempFont := CreateFont(12, 6, 0, 0, FW_EXTRALIGHT, Byte(FALSE), Byte(FALSE), Byte(FALSE), GB2312_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, '宋'); CreateWindowEx(0, 'BUTTON', '退出程序', WS_CHILD or WS_VISIBLE, 60, 20, 70, 25, hForm, ControlID2, HInstance, nil); SendMessage(GetDlgItem(hForm, ControlID2), WM_SETFONT, TempFont, 1); end; WM_COMMAND: begin if (HIWORD(wParam) = BN_CLICKED) then // 单击按钮 begin case LOWORD(wParam) of // 控件ID ControlID1: begin end; ControlID2: SendMessage(hForm, WM_CLOSE, 0, 0); end; end; end; WM_DESTROY: begin PostQuitMessage(0); DeleteObject(TempFont); end; end; end; // 注册类 procedure Register_MainForm; var FormClass: TWndClass; begin FormClass.Style := CS_HREDRAW or CS_VREDRAW; FormClass.lpfnWndProc := @FormProc; FormClass.cbClsExtra := 0; FormClass.cbWndExtra := 0; FormClass.hInstance := SysInit.HInstance; FormClass.hIcon := LoadIcon(HInstance, 'Cool'); FormClass.hCursor := LoadCursor(0, IDC_ARROW); FormClass.hbrBackground := COLOR_WINDOW; FormClass.lpszMenuName := nil; FormClass.lpszClassName := ClassName; RegisterClass(FormClass); end; // 注销类 procedure Unregister_MainForm; begin UnregisterClass(ClassName, HInstance); end; // 建立主 procedure Create_MainForm; begin CreateWindowEx(WS_EX_TOPMOST, ClassName, 'Form1', WS_VISIBLE or WS_TILED or WS_SYSMENU or WS_MINIMIZEBOX or WS_SIZEBOX, 200, 200, 200, 100, 0, 0, HInstance, nil); end; begin Register_MainForm; Create_MainForm; while GetMessage(TheMessage, 0, 0, 0) do begin TranslateMessage(TheMessage); DisPatchMessage(TheMessage); end; end.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值