2009-06-22 83 views
5

Làm cách nào tôi có thể so sánh giá trị của biến có chứa con trỏ trỏ đến hàm có địa chỉ hàm?So sánh con trỏ với giá trị của hàm trong Delphi

Tôi đang duy trì một số mã, và nó là không trong Delphi 2007. Việc kê khai là:

var 
    EditorFrameWindow: Function: HWnd Of Object = Nil; 

Trong một hoạt hình, tôi đã có:

procedure TEditForm.FormActivate(Sender: TObject); 
begin 
    EditorFrameWindow := GetFrameWindow; 
end; 

Và trong hình thức ngừng hoạt động Tôi đã có:

procedure TEditForm.FormDeactivate(Sender: TObject); 
begin 
    if EditorFrameWindow = GetFrameWindow then 
    EditorFrameWindow := nil; 
end; 

Vì vậy, những gì đang xảy ra là biểu mẫu đang bị hủy kích hoạt hai lần và đó là thất bại vì không có gì khác được kích hoạt. FormDeactivate được gọi, nó khớp và toàn bộ EditorFrameWindow được đặt thành (nil, nil) (theo trình gỡ lỗi). Sau đó nó được gọi lại và hàm được lưu trữ trong biến được gọi, nhưng tất nhiên không có một tệp được lưu trữ để nó nhảy qua nil và tạo ra một ngoại lệ.

Tôi nên làm gì để ngăn điều này xảy ra? (Khung đã được thay đổi thành một hệ thống theo thẻ, do đó hoạt động có thể thay đổi.)

+1

Âm thanh như lỗi bên trong GetFrameWindow mà bạn không hiển thị. –

+0

Đối với người mới bắt đầu - tại sao bạn không luôn đặt EditorFrameWindow thành nil trong FormDeactivate? – gabr

+0

Điều đó thực sự chỉ chứa "Kết quả: = Xử lý". – mj2008

Trả lời

14

Would

procedure TEditForm.FormDeactivate(Sender: TObject); 
begin 
    if Assigned(EditorFrameWindow) and (EditorFrameWindow = GetFrameWindow) then 
    EditorFrameWindow := nil; 
end; 

làm việc mỗi cơ hội?

Edit:

Bạn không so sánh địa chỉ chức năng, bạn so sánh kết quả của những chức năng. Vì vậy, mặc dù mã cố định ở trên không còn có thể gây ra ngoại lệ nhưng nó vẫn có thể không làm những gì bạn muốn. Một hàm khác trả về cùng một kết quả cũng sẽ đặt lại trình xử lý sự kiện.

Để thực sự kiểm tra xem biến có được đặt thành trình xử lý sự kiện cụ thể, bạn sẽ cần so sánh cả hai phần tử trong bản ghi TMethod. Một cái gì đó như:

procedure TEditForm.FormDeactivate(Sender: TObject); 
begin 
    if (TMethod(EditorFrameWindow).Code = @TForm1.GetFrameWindow) 
    and (TMethod(EditorFrameWindow).Data = Self) 
    then 
    EditorFrameWindow := nil; 
end; 
+0

Lưu ý rằng trong khi điều này làm việc tôi không thích mã, và do đó sẽ thiết kế lại nó . – mghie

+0

@mghie, vâng, nó có thể không lý tưởng, nhưng như trường hợp với việc duy trì mã mà bạn không hiểu đầy đủ, đôi khi bạn không muốn chạm vào nó nhiều hơn cần thiết! – mj2008

8

Có hai cách bạn có thể muốn so sánh con trỏ phương pháp. Con trỏ phương thức bao gồm hai con trỏ, một con trỏ mã và một con trỏ đối tượng. cách bản địa của Delphi so sánh phương pháp gợi ý so sánh chỉ là gợi ý mã, và nó trông như thế này:

if @EditorWindowMethod = @TEditForm.GetFrameWindow then 
    EditorWindowMethod := nil; 

Nó kiểm tra xem con trỏ mã trong biến EditorWindowMethod phù hợp với địa chỉ bắt đầu của GetFrameWindow phương pháp trong TEditForm. Nó không kiểm tra xem tham chiếu đối tượng trong EditorWindowMethod có giống như Self hay không. Nếu bạn muốn làm cho các tham chiếu đối tượng cũng giống nhau, thì bạn cần phải chia con trỏ phương thức thành các phần cấu thành của nó với bản ghi TMethod, trong đó Mghie's answer chứng minh. (Và có lẽ bạn làm muốn so sánh các tham chiếu đối tượng vì nó âm thanh như bạn có nhiều chỉnh sửa hình thức. Tất cả họ đều có cùng một con trỏ GetFrameWindow mã, nhưng họ có tài liệu tham khảo đối tượng khác nhau.)

Lý do cho sự @ trong mã này là để cho trình biên dịch biết bạn muốn tham chiếu đến các con trỏ phương thức.Nếu không có nó, trình biên dịch sẽ cố gắng để gọi các con trỏ phương pháp, và đó là điều khiến bạn gặp rắc rối. Lần đầu tiên cửa sổ bị hủy kích hoạt, bạn được gọi làEditorWindowMethod và so sánh tay cầm cửa sổ kết quả với giá trị trả lại từ gọiGetFrameWindow. Chúng khớp với nhau, tất nhiên, vì vậy bạn đã bỏ gán EditorWindowMethod. Lần sau khi biểu mẫu bị hủy kích hoạt, bạn đã cố gắng gọi lại số EditorWindowMethod, nhưng đó là một con trỏ rỗng.

Bạn nên cân nhắc việc loại bỏ sự phụ thuộc của mình vào thông báo kích hoạt và hủy kích hoạt. Thay vào đó, chỉ cần kiểm tra xem biểu mẫu có đang hoạt động bên trong GetFrameWindow hay không.

+3

+1 Đây là một trong những câu hỏi lộn xộn (các vấn đề với mã cũ) trở nên có giá trị vì các câu trả lời quá thông tin. – Argalatyr

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