奇淫怪巧之給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就行了!

實現之后的效果,就是這樣的咯


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM