C ++ Windows凭据提供程序进度屏幕

时间:2018-08-20 17:00:03

标签: c++ windows winapi status credential-providers

我正在开发自定义凭据提供程序,并且必须显示带有取消按钮的进度屏幕。我已经在某些凭证提供程序和pgina插件中看到,当凭证提供程序正在工作时,屏幕上会显示一个带有“取消”按钮的屏幕。我已经附上了它的截图。我设法使用以下代码通过“确定”按钮显示错误屏幕:

*pcpgsr = CPGSR_NO_CREDENTIAL_NOT_FINISHED;
SHStrDupW(L"Authentication Failed", ppwszOptionalStatusText);
*pcpsiOptionalStatusIcon = CPSI_ERROR;

现在,我需要显示带有取消按钮的进度屏幕。有什么建议可以实现吗?另外,如何处理按下此按钮时触发的事件?This screen should be displayed when credential provider is working

4 个答案:

答案 0 :(得分:1)

据我所知,您想在后台向用户“等待屏幕”展示一些内容。

您必须运行一个单独的线程来进行后台工作,并更改凭据磁贴的布局,以使可见的一个文本元素仅具有“等待...”内容,并且没有提交按钮。

一旦您的后台线程完成其工作,您可以显示“提交”按钮,并让用户继续登录。

例如,看看嵌入式Smartcard Credential Porvider及其在插入和取出卡时的行为。

答案 1 :(得分:1)

@ js.hrt您可以将主线程作为对话框运行,而后台线程则可以运行。取消按钮将是对话框中的控件,允许将其取消。如果您需要更多信息,请告诉我,我可以提供一些详细信息,因为这是我们的方法。

@ js.hrt简要地说,您需要两个类:对话框和线程。 创建对话框时,它将创建一个线程,该线程将运行所需的线程,并显示“取消”按钮。单击它将终止您的线程。下面的一些代码。希望对您有所帮助。

class Thread  {
    public:
        Thread(GUI* object);
        virtual ~Thread();
        bool start( bool )   {
        ::CreateThread( NULL, 0, threadRun, lpParameter, dwCreationFlags, 
             &m_dwThreadId );
        }
        static DWORD WINAPI threadRun( void* lpVoid )   {
            DWORD dwReturn( 0 );
            dwReturn = m_object->yourProcessToRun();
            return dwReturn;
         }
    protected:
        GUI* m_object;
        Runnable* m_lpRunnable;
};

然后,为您的用户界面创建类,类似于此

#include "atlwin.h"

class GUI: public CDialogImpl<GUI>  {
   public:
      enum { IDD = IDD_FOR_YOUR_DIALOG  };
      GUI();
     ~GUI();
      BEGIN_MSG_MAP(GUI)
          MESSAGE_HANDLER(WM_INITDIALOG,OnInitDialog)
          COMMAND_ID_HANDLER(ID_CANCEL,OnCancel)
          MESSAGE_HANDLER(WM_TIMER,OnTimer)
          MESSAGE_HANDLER(WM_DESTROY,OnDestroy)
      END_MSG_MAP()
      LRESULT OnInitDialog(UINT,WPARAM,LPARAM, BOOL&) {
          myThread = new Thread(this);
          m_nTimerID = SetTimer(1,3000,NULL);
          myThread->start();
      }
      LRESULT OnCancel(WORD,WORD,HWND,BOOL& )  {
          if(NULL != myThread)  {
             DWORD exitCode = 0;
             myThread->getExitCode(exitCode);
             if(exitCode == STILL_ACTIVE)
                 myThread->terminate();
             delete myThread;
              myThread = NULL;
           }
           EndDialog(IDCANCEL);
           return true;
      }        
      LRESULT OnTimer(UINT,WPARAM wParam,LPARAM,BOOL&)  {
          if(wParam != m_nTimerID)
              return FALSE;
          m_timerticks++;
          return FALSE;
      }
      LRESULT OnDestroy(UINT,WPARAM,LPARAM,BOOL&)  {
          KillTimer(m_nTimerID);
          return FALSE;
      }
      virtual int yourProcessToRun() {};
      void onFinishProgress(int retCode = IDOK) {
          if (retCode != IDCANCEL)  {
              delete myThread;
              myThread = NULL;
              KillTimer(m_nTimerID);
              EndDialog(retCode);
           }
       }

      private:
          Thread* myThread;
           UINT    m_nTimerID;
           UINT    m_timerticks;
 };

用于对话的资源可能是这样的:

IDD_FOR_YOUR_DIALOG DIALOGEX 0, 0, 309, 80
       STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP 
       | WS_CAPTION
CAPTION "Whatever"
FONT 8, "MS Shell Dlg", 400, 0, 0x0
BEGIN
    PUSHBUTTON      "Cancel",ID_CANCEL,113,50,84,14
    CTEXT           "Static",IDC_FOR_SOMETHING,7,7,295,20
END

@ js.hrt如果您不介意发布代码,则将其运行。          无法直接评论您的留言,因为我受网站的限制          要求

答案 2 :(得分:0)

@ js.hrt根据您的请求。

class Thread  {
public:
    Thread(GUI* object);
    virtual ~Thread();
    bool start( bool )   {
    ::CreateThread( NULL, 0, threadRun, lpParameter, dwCreationFlags, 
         &m_dwThreadId );
    }
    static DWORD WINAPI threadRun( void* lpVoid )   {
        DWORD dwReturn( 0 );
        dwReturn = m_object->yourProcessToRun();
        return dwReturn;
     }
protected:
    GUI* m_object;
    Runnable* m_lpRunnable;

};     然后,为您的UI编写类,类似于此

#include "atlwin.h"

class GUI: public CDialogImpl<GUI>  {
public:
  enum { IDD = IDD_FOR_YOUR_DIALOG  };
  GUI();
 ~GUI();
  BEGIN_MSG_MAP(GUI)
      MESSAGE_HANDLER(WM_INITDIALOG,OnInitDialog)
      COMMAND_ID_HANDLER(ID_CANCEL,OnCancel)
      MESSAGE_HANDLER(WM_TIMER,OnTimer)
      MESSAGE_HANDLER(WM_DESTROY,OnDestroy)
  END_MSG_MAP()
  LRESULT OnInitDialog(UINT,WPARAM,LPARAM, BOOL&) {
      myThread = new Thread(this);
      m_nTimerID = SetTimer(1,3000,NULL);
      myThread->start();
  }
  LRESULT OnCancel(WORD,WORD,HWND,BOOL& )  {
      if(NULL != myThread)  {
         DWORD exitCode = 0;
         myThread->getExitCode(exitCode);
         if(exitCode == STILL_ACTIVE)
             myThread->terminate();
         delete myThread;
          myThread = NULL;
       }
       EndDialog(IDCANCEL);
       return true;
  }        
  LRESULT OnTimer(UINT,WPARAM wParam,LPARAM,BOOL&)  {
      if(wParam != m_nTimerID)
          return FALSE;
      m_timerticks++;
      return FALSE;
  }
  LRESULT OnDestroy(UINT,WPARAM,LPARAM,BOOL&)  {
      KillTimer(m_nTimerID);
      return FALSE;
  }
  virtual int yourProcessToRun() {};
  void onFinishProgress(int retCode = IDOK) {
      if (retCode != IDCANCEL)  {
          delete myThread;
          myThread = NULL;
          KillTimer(m_nTimerID);
          EndDialog(retCode);
       }
   }

  private:
      Thread* myThread;
       UINT    m_nTimerID;
       UINT    m_timerticks;

};     对话框的资源可能是这样的:

IDD_FOR_YOUR_DIALOG DIALOGEX 0, 0, 309, 80
   STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP 
   | WS_CAPTION
CAPTION "Whatever"
FONT 8, "MS Shell Dlg", 400, 0, 0x0
BEGIN
    PUSHBUTTON      "Cancel",ID_CANCEL,113,50,84,14
    CTEXT           "Static",IDC_FOR_SOMETHING,7,7,295,20
END

答案 3 :(得分:0)

我假设您正在寻找IConnectableCredentialProviderCredential::Connect()。 您需要实现IConnectableCredentialProviderCredential接口,并将逻辑放入Connect()函数中。按下“提交”按钮后立即调用。 Connect()函数将为您提供IQueryContinueWithStatus界面。在此界面中,您需要定期调用QueryContinue()函数,以处理“取消”按钮或某些系统事件。

有关更多信息,请参见本文:https://docs.microsoft.com/en-us/windows/win32/api/credentialprovider/nf-credentialprovider-iconnectablecredentialprovidercredential-connect