⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dlgdyn.dpr

📁 这一系列是我平时收集的pascal深入核心变成
💻 DPR
字号:
program DlgDyn;

{$R DlgDyn.res}

uses Windows, Messages, DlgTmplt in 'DlgTmplt.pas', DynDlg in 'DynDlg.pas';

const
  IDD_DLGDYN   = 101; // 主窗体对话框模板资源ID
  IDI_DLGDYN   = 102; // 主窗体对话框图标资源ID
  IDC_MODAL    = 1000; // 主窗体'建立模态对话框'按钮ID
  IDC_MODELESS = 1001; // 主窗体'建立/删除非模态对话框'按钮ID

var
 // 在本程序中, 主窗体是一个模态对话框, 当再产生一个非模态的对话框, 它的'键盘接口'
 // 将不起作用. 因为主窗体的消息循环不会为后来的非模态对话框调用IsDialogMessage(),
 // 为了使非模态对话框响应特殊按键(如切换焦点的Tab), 作者安装了一个消息过滤器钩子,
 // 下面这个变量保存非模态对话框的句柄, 消息过滤器钩子会为他调用IsDialogMessage()
  g_hWndModeless: HWND = 0;

 // 消息过滤器钩子句柄, 此钩子为非模态对话框g_hWndModeless添加'键盘接口'
  g_hHookMsgFilter: HHOOK = 0;

 // 主窗体WM_INITDIALOG消息处理
function DlgDyn_OnInitDialog(hWnd, hWndFocus: HWND; lParam: LPARAM): BOOL;
begin
 // 设置主窗体对话框图标
  SendMessage(hWnd, WM_SETICON, ICON_BIG, LoadIcon(HInstance, MakeIntResource(IDI_DLGDYN)));

 // 允许系统设置默认焦点
  Result := TRUE;
end;

 // 主窗体WM_COMMAND消息处理
procedure DlgDyn_OnCommand(hWnd: HWND; id: Integer; hWndCtl: HWND; codeNotify: UINT);
var
  DlgTemplatePt: PDlgTemplateEx;
begin
  case (id) of
    IDOK, IDCANCEL:
      begin
       // 删除窗体, 停止循环
        EndDialog(hWnd, id);
      end;

    IDC_MODAL:
      begin
       // 产生对话框内存结构
        DlgTemplatePt := BuildDynamicDlgBox(FALSE);
        if (DlgTemplatePt = nil) then Exit;

       // 根据结构建立对话框
        DialogBoxIndirect(HInstance, PDlgTemplate(DlgTemplatePt)^, hWnd, @DynDlg_DlgProc);

       // 释放对话框结构内存
        DlgTemplate_Free(DlgTemplatePt);
      end;

    IDC_MODELESS:
      begin
       // 如果非模态对话框已存在, 则删除, 否则建立
        if IsWindow(g_hWndModeless) then
        begin
         // 删除窗体, 句柄清零
          DestroyWindow(g_hWndModeless);
          g_hWndModeless := 0;
        end else
        begin
         // 产生对话框内存结构
          DlgTemplatePt := BuildDynamicDlgBox(TRUE);
          if (DlgTemplatePt = nil) then Exit;

         // 根据结构建立对话框
          g_hWndModeless := CreateDialogIndirect(HInstance,
            PDlgTemplate(DlgTemplatePt)^, hWnd, @DynDlg_DlgProc);

         // 释放对话框结构内存          
          DlgTemplate_Free(DlgTemplatePt);
        end;

       // 根据非模态对话框状态设置按钮文字
        if IsWindow(g_hWndModeless) then
          SetWindowText(hWndCtl, 'Destroy dynamic modeless dialog box')
        else
          SetWindowText(hWndCtl, 'Create dynamic modeless dialog box');
      end;
  end; // END: case (id) of ..
end;

 // 主窗体对话框过程
function DlgDyn_DlgProc(hWnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM): BOOL; stdcall;
begin
  case (uMsg) of
    WM_INITDIALOG:
      begin
        Result := BOOL(SetWindowLong(hWnd, DWL_MSGRESULT,
          Longint(DlgDyn_OnInitDialog(hWnd, wParam, lParam))));
      end;
    WM_COMMAND:
      begin
        DlgDyn_OnCommand(hWnd, LOWORD(wParam), lParam, HIWORD(wParam));
        Result := TRUE;
      end;
    else Result := FALSE;
  end;
end;

 // 消息过滤钩子回调函数, 为非模态对话框调用IsDialogMessage(),
 // 从而可以对其键盘消息作'对话框式'的处理, 比如Tab键转移焦点
function DlgDyn_MsgFilterProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
const
{$J+}
 // 这个静态变量用于防止下面的IsDialogMessage()调用引起无限的递归,
 // 因为IsDialogMessage()会在第一时间调用所有已经安装的消息过滤钩子
  fRecurse: BOOL = FALSE;
{$J-}
begin
 // 如果本次被调用是由于之前调用的IsDialogMessage(), 则直接返回
  if (fRecurse) then
  begin
   // 返回0表示没有处理消息, 让系统作正常处理, 例如让IsDialogMessage()继续处理,
   // 注意: 我们没有调用CallNextHookEx(), 因为不希望同一个消息多次经过钩子链 ..
    Result := 0;
    Exit;
  end;

 // 这里, 移除钩子然后重新挂钩, 使得我们的钩子总是处于系统钩子链的最前面,
 // 这是必要的, 因为, 处于我们钩子之前的钩子可能会因为一个消息被调用两次,
 // 把我们的钩子放到链表的最前面, 可以保证我们的钩子第一个被调用, 当遇到
 // 因我们调用IsDialogMessage()引起的钩子调用, 可阻止信息通过后面的钩子链
  UnhookWindowsHookEx(g_hHookMsgFilter);
  g_hHookMsgFilter := SetWindowsHookEx(WH_MSGFILTER, @DlgDyn_MsgFilterProc, 0, GetCurrentThreadId());

 // 将钩子信息传递给钩子链中的下一个钩子函数, 并得到其返回值
 // (麻子注: 如果把这句移到重新挂钩的前面会不会更合适一些呢)
  Result := CallNextHookEx(g_hHookMsgFilter, nCode, wParam, lParam);

 // 如果后面的钩子允许作其他的处理, 并且非模态对话框句柄有效
  if (Result = 0) and IsWindow(g_hWndModeless) then
  begin
   // 设置fRecurse为TRUE防止无限递归, 再调用IsDialogMessage()分发消息到窗体过程,
   // IsDialogMessage()的返回值表示消息是否被处理了, 此处作为钩子返回值正合适 ..
    fRecurse := TRUE;
    Result := LRESULT(IsDialogMessage(g_hWndModeless, PMsg(lParam)^));
    fRecurse := FALSE;
  end;
end;

 // 程序'主线程'入口
begin
 // 安装消息过滤钩子,
 // 使得有机会为非模态对话框调用IsDialogMessage(),
 // 从而可以对其键盘消息作'对话框式'的'特殊'的处理
  g_hHookMsgFilter := SetWindowsHookEx(WH_MSGFILTER, @DlgDyn_MsgFilterProc, 0, GetCurrentThreadId());

 // 建立主窗体对话框 
  DialogBox(HInstance, MakeIntResource(IDD_DLGDYN), 0, @DlgDyn_DlgProc);

 // 移除消息过滤钩子
  UnhookWindowsHookEx(g_hHookMsgFilter);
end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -