2016-09-01 12 views
5

Tôi cần thực hiện một số thay đổi đối với TaskDialog trước khi nó được hiển thị cho người dùng. Nó khá đơn giản để sử dụng các cuộc gọi Windows API để làm việc với mỗi điều khiển trên hộp thoại. Tôi cần phải chắc chắn hơn nút mà tôi đã tìm thấy. Tôi đã có thể mong đợi để tìm một nơi mà tôi có thể đọc kết quả nút sẽ cung cấp cho nếu ép.Khi lặp qua các điều khiển trên biểu mẫu, làm cách nào tôi có thể xác định các nút cụ thể?

nói cách khác, nếu tôi nhấn một nút có thể gây ra giá trị trả về (trong Delphi, nó được gọi là kết quả phương thức) là 100, tôi đã dự kiến ​​sẽ có một cuộc gọi API mà tôi có thể gọi để tìm hiểu "giá trị trả về" của nút sẽ là. Tôi chưa tìm thấy bất kỳ cuộc gọi nào như vậy.

Tôi không muốn dựa vào văn bản nút ..

Đây là những gì tôi có cho đến nay.

function EnumWindowsProcToFindDlgControls(hWindow: HWND; _param:LPARAM): BOOL; stdcall; 
var 
    sClassName:string; 
    hBMP:THandle; 
    i:integer; 
begin 
    SetLength(sClassName, MAX_PATH); 
    GetClassName(hWindow, PChar(sClassName), MAX_PATH); 
    SetLength(sClassName, StrLen(PChar(sClassName))); 

    if sClassName='Button' then 
    begin  
     // always 0... 
     i:=GetDlgCtrlID(hWindow); 

     if (i=100) or (i=102) then 
     begin 
      hBmp := LoadImage(HInstance, 'DISA', IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE or LR_LOADTRANSPARENT); 

      SendMessage(hWindow, BM_SETIMAGE, WPARAM(IMAGE_BITMAP), LPARAM(hBmp)); 
     end; 
    end; 

    // keep looking 
    Result:=true; 
end; 

procedure TForm2.TaskDialog1DialogConstructed(Sender: TObject); 
begin 
    EnumChildWindows(TaskDialog1.Handle, @EnumWindowsProcToFindDlgControls, 0); 
end; 

Tôi nghi ngờ không hoàn toàn "đáng kính" khi làm những việc như thế này với hộp thoại.

Đây là ứng dụng Delphi 10 Win32 sử dụng thành phần VCL TTaskDialog của Delphi, đây là một tính năng bao quanh tính năng hộp thoại nhiệm vụ của Windows. trước khi nó được hiển thị, sự kiện OnConstructed kích hoạt, thực thi mã này.

Cảm ơn sự giúp đỡ của bạn!

+0

Tôi không đọc mã của bạn, nhưng bạn có thể xác định các nút cụ thể bằng ID của họ. Bạn chỉ cần biết ID của các điều khiển bạn muốn thay đổi. –

+0

Dường như ID luôn bằng 0 khi được xây dựng bởi thói quen hộp thoại nhiệm vụ trong cửa sổ. –

+0

FWIW, bạn có thể thay thế 'SetLength (sClassName, StrLen (PChar (sClassName));' và mã tương tự bằng 'sClassName: = PChar (sClassName);'. Điều đó sẽ đạt được như vậy. –

Trả lời

9

Nút Win32 không có "giá trị trả về", đó là lý do tại sao không có API để lấy giá trị như vậy từ chúng. Những gì bạn đang nghĩ đến là nghiêm chỉnh một tính năng VCL.

Về Win32 API, một nút có thể có một ID kiểm soát, và trong trường hợp của MessageBox(), ví dụ, giá trị ID tiêu chuẩn như IDOK, IDCANCEL, vv được gán cho nút thoại. Khi một nút được nhấp và hộp thoại được đóng lại, ID điều khiển của nút được sử dụng làm giá trị trả về hàm.

Nhưng hộp thoại tác vụ không sử dụng ID kiểm soát, đó là lý do tại sao bạn không thấy bất kỳ được gán cho các nút hộp thoại.

Để xác định một nút thoại nhiệm vụ cụ thể, tôi có thể nghĩ đến hai cách:

  1. trong liệt kê con, lấy văn bản chú thích của mỗi nút (GetWindowText()), và so sánh với chú thích bạn quan tâm Chỉ cần. biết rằng các nút tiêu chuẩn (từ thuộc tính TTaskDialog.CommonButtons) sử dụng văn bản được bản địa hóa, không làm cho tùy chọn này phù hợp để định vị các nút tiêu chuẩn trừ khi bạn có quyền kiểm soát cài đặt ngôn ngữ của ứng dụng.

  2. gửi hộp thoại TDM_ENABLE_BUTTON tin nhắn để tạm thời vô hiệu hóa nút mong muốn có ID nhất định, sau đó liệt kê các điều khiển của hộp thoại cho đến khi bạn tìm thấy cửa sổ con bị tắt (sử dụng IsWindowEnabled()), sau đó bật lại điều khiển. Sau đó, bạn có thể thao tác cửa sổ tìm thấy nếu cần.

    Đối Task Dialog messagesTask Dialog Notifications hoạt động trên các nút (như TDN_BUTTON_CLICKED, mà gây nên sự kiện TTaskDialog.OnButtonClicked), các nút tiêu chuẩn sử dụng ID như IDOK, IDCANCEL, vv trong khi các nút tùy chỉnh (từ TTaskDialog.Buttons tài sản) sử dụng tài sản ModalResult của họ như là ID của họ .

    Bạn có thể gửi TDM_ENABLE_BUTTON trực tiếp qua SendMessage() cho các nút tiêu chuẩn hoặc thông qua thuộc tính TTaskDialogBaseButtonItem.Enabled cho các nút tùy chỉnh.

Đối # 2, công trình này khi tôi thử nó:

uses 
    Winapi.CommCtrl; 

function FindDisabledDlgControl(hWindow: HWND; _param: LPARAM): BOOL; stdcall; 
type 
    PHWND = ^HWND; 
begin 
    if not IsWindowEnabled(hWindow) then 
    begin 
    PHWND(_param)^ := hWindow; 
    Result := False; 
    end else 
    Result := True; 
end; 

procedure TForm2.TaskDialog1DialogConstructed(Sender: TObject); 
var 
    hButton: HWND; 
begin 
    // common tcbOk button 
    SendMessage(TaskDialog1.Handle, TDM_ENABLE_BUTTON, IDOK, 0); 
    hButton := 0; 
    EnumChildWindows(TaskDialog1.Handle, @FindDisabledDlgControl, LPARAM(@hButton)); 
    SendMessage(TaskDialog1.Handle, TDM_ENABLE_BUTTON, IDOK, 1); 
    if hButton <> 0 then 
    begin 
    // use hButton as needed... 
    end; 

    // custom button 
    TaskDialog1.Buttons[0].Enabled := False; 
    hButton := 0; 
    EnumChildWindows(TaskDialog1.Handle, @FindDisabledDlgControl, LPARAM(@hButton)); 
    TaskDialog1.Buttons[0].Enabled := True; 
    if hButton <> 0 then 
    begin 
    // use hButton as needed... 
    end; 
end; 
+0

Cảm ơn bạn đã trả lời chi tiết và sáng tạo của bạn (hoạt động nổi tiếng)! Điều này là tốt hơn nhiều so với dựa vào văn bản nút (không phải là một tình huống chấp nhận được đối với chúng tôi). Tôi sẽ chắc chắn để thử nó trên hệ thống tối thiểu của chúng tôi quá ... Tìm hiểu một số công cụ tốt làm điều này ... –

+0

Điều gì nếu đã có một nút bị vô hiệu hóa trong danh sách các điều khiển, Làm thế nào bạn sẽ biết bạn có cửa sổ chính xác? –

Các vấn đề liên quan