2012-12-12 28 views
3

我使用InternetErrorDlg顯示請登錄/密碼(這是德爾福,但我想很明顯)InternetErrorDlg顯示不保存密碼

function ShowLoginDlg(Request: HINTERNET): boolean; 
var 
    DlgError: Cardinal; 
begin 
    DlgError := InternetErrorDlg(GetDesktopWindow, Request, 0, 
    FLAGS_ERROR_UI_FILTER_FOR_ERRORS or 
    FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS or 
    FLAGS_ERROR_UI_FLAGS_GENERATE_DATA, PPointer(nil)^{like NULL in C/C++}); 
    if DlgError = ERROR_CANCELLED then Abort; // Abort raises exception 
    if (DlgError <> ERROR_SUCCESS) and (DlgError <> ERROR_INTERNET_FORCE_RETRY) then 
    RaiseLastOSError(DlgError); // RaiseLastOSError raises exception 
    Result := DlgError = ERROR_INTERNET_FORCE_RETRY; 
end; 

while True do 
begin 
    SendRequest(Request); 
    if not ((GetStatusCode(Request) = 401) and ShowLoginDlg(Request)) do 
    Continue; 
    CheckStatusCode(Request); // raises exception if status code >= 400 
end; 

,並有一個問題。即使用戶選中「保存密碼」,密碼也不會真的保存爲 。所以,當我關閉並再次打開我的程序時,web資源返回401給我,我必須再次顯示登錄對話框。

任何想法??

如果我通過RRUZ的建議添加FLAGS_ERROR_UI_SERIALIZE_DIALOGS,我沒有得到任何效果。我的回調沒有被調用,密碼也沒有保存。

function InternetAuthNotifyCallback(
     dwContext: DWORD; // as passed to InternetErrorDlg 
     dwReturn: DWORD; // error code: success, resend, or cancel 
     lpReserved: Pointer // reserved: will be set to null 
    ): DWORD; stdcall; // stdcall, is it right? 
begin 
    Result := 0; // What do I have to do?? 
end; 

    type 
    PFN_AUTH_NOTIFY = function(
     dwContext:DWORD; 
     dwReturn:DWORD; 
     lpReserved:Pointer): DWORD; stdcall; 
    PINTERNET_AUTH_NOTIFY_DATA = ^INTERNET_AUTH_NOTIFY_DATA; 
    INTERNET_AUTH_NOTIFY_DATA = packed record 
     cbStruct: DWORD; 
     dwOptions: DWORD; 
     pfnNotify: PFN_AUTH_NOTIFY; 
     dwContext: PDWORD; 
    end; 

    function ShowLoginDlg(Request: HINTERNET): boolean; 
    var 
    DlgError: Cardinal; 
    PData: Pointer; 
    Data: INTERNET_AUTH_NOTIFY_DATA; 
    begin 
    ZeroMemory(@Data, SizeOf(Data)); 
    Data.cbStruct := SizeOf(Data); 
    Data.pfnNotify := InternetAuthNotifyCallback; 
    PData := @Data; // if I set PData := Pointer(1) there is **not** AV!!!! 
      // InternetErrorDlg don't use this parameter??? 
    DlgError := InternetErrorDlg(Application.MainForm.Handle, Request, 0, 
     FLAGS_ERROR_UI_FILTER_FOR_ERRORS or 
     FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS or 
     FLAGS_ERROR_UI_FLAGS_GENERATE_DATA or 
     FLAGS_ERROR_UI_SERIALIZE_DIALOGS, 
     PData); // really InternetErrorDlg get pointer to PData, because in Delphi this param is passed by ref 
    if DlgError = ERROR_CANCELLED then Abort; 
    if (DlgError <> ERROR_SUCCESS) and (DlgError <> ERROR_INTERNET_FORCE_RETRY) then 
     RaiseLastOSError(DlgError); 
    Result := DlgError = ERROR_INTERNET_FORCE_RETRY; 
    end; 

回答

3

根據有關InternetErrorDlg函數的文檔,您必須在方法調用的 FLAGS_ERROR_UI_SERIALIZE_DIALOGS標誌。

FLAGS_ERROR_UI_SERIALIZE_DIALOGS

序列化認證的對話框,用於在 密碼緩存項併發請求。 lppvData參數應該包含指向INTERNET_AUTH_NOTIFY_DATA結構的指針的地址 ,並且客戶端應該實現線程安全的非阻塞回調函數 。

+0

我更新了我的問題以重播您。 – Jack128