奇淫怪巧之给Delphi的PrintDialog增加一个页码选定范围打印的Edit

简介:

  在Delphi中使用PrintDialog打印对话框的时候,这个控件有三个选项,就是PrintRang那个属性的三个选项,其中有一个选项三,让我们自定义选择页码范围来打印。但是比较蛋疼的是,这个地方选中了之后啥子效果都没有。无法制定自己的页码范围,很是蛋疼。这里实际上应该要有一个Edit之类的编辑框的,这样可以让用户输入1,2,3-4之类的页码范围来整就比较人性化了。起初以为是自己没有指定某属性神马的导致,于是在控件的各个属性中找,找的我蛋都要裂开了,都没找出来似乎是隐藏了那个Edit的属性。。。。无果,整开了PrintDialog的源码看。也未发现相关的代码。咋办,咋办呢。路总是人走出来的,目的就是要在这个弹出的对话框上加一个编辑框就OK了,方式很多,可以在弹出来之后,查找句柄,然后创建一个Edit,然后SetParent就上去了。这是一方面,另外一方面,就是要配合对话框上,用户点击上面的选项来相应的联动这个Edit为可用或非可用状态。这个自然也是有办法的,我首先想到的就是Hook了,于是就用Hook整了,WH_CallWndProc消息处理过程函数的Hook,就行了。至于是要拦截神马消息,嘿嘿,这个是WinSDK的范畴,不熟悉的人,去翻番书,或者百度一番,就可以知道是WM_Command这个消息来处理窗口中的某些控件的消息处理的。首先就是要获取那个弹出的打印对话框的句柄了,我说过了可以用FindWindow来找。不过我这里要使用消息过程钩子,那么自然就不要这个了,直接从钩子中获取对话框句柄,会更加Happy。看看PrintDialog的代码,俺们可以知道,神马PrintDialog,OpenDialog,FontDialog打开都要触发WM_InitDialog这个消息,就是初始化对话框的消息。所以,第一步,俺们就拦截这个消息就 可以获取到句柄,然后创建俺们的Edit,然后将Edit设置到对话框中,俺们需要他在的位置。第二步,就是来拦截WM_Command,然后来处理和用户点击的联动处理咯。然后就是在对话框的Destroy消息中注销Hook,释放Edit。于是这个过程就OK了

首先在打开对话框之前,注册我们的过程处理钩子,必须要之前注册,因为要拦截WM_InitDialog消息嘛

procedure TForm1.Button1Click(Sender: TObject);
begin
  CEdit := TEdit.CreateParented(Application.Handle);
  CEdit.Parent := Application.MainForm;
  Hok := SetWindowsHookEx(WH_CALLWNDPROC,WNDProcHook,HInstance,GetCurrentThreadId);
  if PrintDialog1.Execute then
  begin
    ShowMessage(CEdit.Text);
  end;
  UnhookWindowsHookEx(HOK);
  FreeAndNil(CEdit);
end;

然后是钩子函数过程处理

var
  DownBtnID: Integer;
  PrntDlgHandle: THandle;
  CEdit: TEdit;
function WNDProcHook(code: Integer; wparam: WPARAM; lparam: LPARAM): LRESULT stdcall;
var
  msg: PCWPSTRUCT;
  wNotifyCode,wID: Word;
  r,WinR: TRect;
  DwonBtnHandle: THandle;
begin
  if code < 0 then
    Result := CallNextHookEx(Hok, code, wparam, lparam)
  else
  begin
    msg := PCWPSTRUCT(lparam);
    case msg.message of
    WM_INITDIALOG:
       begin
          PrntDlgHandle := msg.hwnd;
          DwonBtnHandle := FindWindowEx(PrntDlgHandle,0,'Button','打印范围');
          Windows.SetParent(CEdit.Handle,DwonBtnHandle);
          GetWindowRect(DwonBtnHandle,WinR);
          CEdit.Visible := True;
          DwonBtnHandle := FindWindowEx(PrntDlgHandle,0,'Button','选定范围(&S)');
          CEdit.Enabled := SendMessage(DwonBtnHandle,BM_GETCHECK,0,0) = 1;
          GetWindowRect(DwonBtnHandle,r);
          DownBtnID := GetDlgCtrlID(DwonBtnHandle);
          CEdit.Left := r.Right - WinR.Left;
          CEdit.Top := r.Top - WinR.Top;
       end;
    WM_COMMAND:
       begin
          if msg.hwnd = PrntDlgHandle then
          begin
            wNotifyCode := HIWORD(Msg.wparam);
            wID := LOWORD(Msg.wParam);
            if wNotifyCode = BN_CLICKED then
            begin
              CEdit.Enabled := wID = DownBtnID
            end;
          end;
       end;
    WM_DESTROY:
       begin
         //UnhookWindowsHookEx(HOK);
         //Hok := 0;
         //FreeAndNil(CEdit);
       end;
    end;
    Result := 0;
  end;
end;

  可见,我这里注销了WM_Destroy中的处理。目的是因为俺们还需要返回这个Edit中的内容嘛,所以我们直接在使用完了之后注销钩子,释放Edit就行了!

实现之后的效果,就是这样的咯



本文转自 不得闲 博客园博客,原文链接: http://www.cnblogs.com/DxSoft/archive/2013/04/22/3035565.html ,如需转载请自行联系原作者

相关文章
QT软件开发: QPlainTextEdit当做日志显示窗口
QT软件开发: QPlainTextEdit当做日志显示窗口
611 0
QT软件开发: QPlainTextEdit当做日志显示窗口
|
4月前
[MFC] Edit控件上的数据(可控固定位数)显示
[MFC] Edit控件上的数据(可控固定位数)显示
31 0
|
5月前
|
缓存
《QT从基础到进阶·二十二》QGraphicsView显示大量图形项item导致界面卡顿的解决办法
《QT从基础到进阶·二十二》QGraphicsView显示大量图形项item导致界面卡顿的解决办法
209 0
|
7月前
|
IDE 编译器 开发工具
善用 vs 中的错误列表和输出窗口,高效查找 C++ 多工程编译错误
善用 vs 中的错误列表和输出窗口,高效查找 C++ 多工程编译错误
PS的标题栏以选项卡方式打开名字太长,导致切换标题的时候不方便,如何缩短标题栏?
Q:如图:PS的标题栏以选项卡方式打开名字太长,导致切换标题的时候不方便,如何缩短标题栏?
350 0
PS的标题栏以选项卡方式打开名字太长,导致切换标题的时候不方便,如何缩短标题栏?
【C#】【平时练习】将左边列表框(List)的内容(月份)添加到右边列表框。最终右侧显示的内容(月份)要保持一定顺序
【C#】【平时练习】将左边列表框(List)的内容(月份)添加到右边列表框。最终右侧显示的内容(月份)要保持一定顺序
99 0
【C#】【平时练习】将左边列表框(List)的内容(月份)添加到右边列表框。最终右侧显示的内容(月份)要保持一定顺序
|
C++
winForm开发问题,vs的bug,Datagridview始终不能编辑!
如果更改Datagridview启用编辑为不选中 则项目在生成时会将Datagridview的Columns的ReadOnly更改为true 再次启用 DataGridView的编辑,但Datagridview的Columns的ReadOnl...
1017 0
|
XML 数据格式 容器
如何找到SAP UI5控件ID生成的准确时间点和代码位置
如何找到SAP UI5控件ID生成的准确时间点和代码位置
如何找到SAP UI5控件ID生成的准确时间点和代码位置
SAP BSP页面里,每次在Text Area里敲字后如何统计输入的总字数
SAP BSP页面里,每次在Text Area里敲字后如何统计输入的总字数
96 0
SAP BSP页面里,每次在Text Area里敲字后如何统计输入的总字数
|
C# 移动开发
写一个去除AI2XAML注释及多余数字位数的WPF窗体程序
原文:写一个去除AI2XAML注释及多余数字位数的WPF窗体程序 使用正则表达式去除多余注释及冗余数字位,关键代码:            string pattern = @"/b(/d+)/.
1021 0