CredentialProvider提供的UI控件与使用方法

前言:在上一篇博客中对CredentialProvider基本概念、个人理解等做了阐述,其中提到CredentialProvider提供了一定的UI控件可供开发者调用,且开发者只可以使用CredentialProvider接口所提供的控件,不可自定义控件或者美化CredentialProvider接口所提供的控件,本文则结合具体的UI控件图例对CredentialProvider所提供的UI控件进行介绍。

CredentialProvider UI控件简介:如图所示,CredentialProvider提供的UI控件共有9种,开发者可以根据需要自行选择组合使用。该图例对应的代码来自开源的样例代码编译部署所得的截图,样例代码地址为:CredentialProviders/V2 Credential Provider Sample at master · alexyack/CredentialProviders

UI控件的定义为CREDENTIAL_PROVIDER_FIELD_TYPE枚举,开发在使用时只需指定需要的控件枚举即可,CREDENTIAL_PROVIDER_FIELD_TYPE的具体定义如下:

// credentialprovider.h:359

typedef /* [v1_enum] */ 
enum _CREDENTIAL_PROVIDER_FIELD_TYPE
{
    CPFT_INVALID	= 0,
    CPFT_LARGE_TEXT	= ( CPFT_INVALID + 1 ) ,
    CPFT_SMALL_TEXT	= ( CPFT_LARGE_TEXT + 1 ) ,
    CPFT_COMMAND_LINK	= ( CPFT_SMALL_TEXT + 1 ) ,
    CPFT_EDIT_TEXT	= ( CPFT_COMMAND_LINK + 1 ) ,
    CPFT_PASSWORD_TEXT	= ( CPFT_EDIT_TEXT + 1 ) ,
    CPFT_TILE_IMAGE	= ( CPFT_PASSWORD_TEXT + 1 ) ,
    CPFT_CHECKBOX	= ( CPFT_TILE_IMAGE + 1 ) ,
    CPFT_COMBOBOX	= ( CPFT_CHECKBOX + 1 ) ,
    CPFT_SUBMIT_BUTTON	= ( CPFT_COMBOBOX + 1 ) 
} 	CREDENTIAL_PROVIDER_FIELD_TYPE;

CredentialProvider UI控件的使用:UI控件的使用可以参考上面样例中的common.h,根据个人开发需要添加或者删除对应的控件即可,其中SAMPLE_FIELD_ID中的SFI_NUM_FIELDS必须保留,且只能放在最后一个,其表明自定义凭据所包含的UI字段数量。common.h源码如下所示:

// common.h
// https://github.com/alexyack/CredentialProviders/blob/master/V2%20Credential%20Provider%20Sample/C%2B%2B/common.h

#pragma once
#include "helpers.h"

// The indexes of each of the fields in our credential provider's tiles. Note that we're
// using each of the nine available field types here.
enum SAMPLE_FIELD_ID
{
    SFI_TILEIMAGE         = 0,
    SFI_LABEL             = 1,
    SFI_LARGE_TEXT        = 2,
    SFI_PASSWORD          = 3,
    SFI_SUBMIT_BUTTON     = 4,
    SFI_LAUNCHWINDOW_LINK = 5,
    SFI_HIDECONTROLS_LINK = 6,
    SFI_FULLNAME_TEXT     = 7,
    SFI_DISPLAYNAME_TEXT  = 8,
    SFI_LOGONSTATUS_TEXT  = 9,
    SFI_CHECKBOX          = 10,
    SFI_EDIT_TEXT         = 11,
    SFI_COMBOBOX          = 12,
    SFI_NUM_FIELDS        = 13,  // Note: if new fields are added, keep NUM_FIELDS last.  This is used as a count of the number of fields
};

// The first value indicates when the tile is displayed (selected, not selected)
// the second indicates things like whether the field is enabled, whether it has key focus, etc.
struct FIELD_STATE_PAIR
{
    CREDENTIAL_PROVIDER_FIELD_STATE cpfs;
    CREDENTIAL_PROVIDER_FIELD_INTERACTIVE_STATE cpfis;
};

// These two arrays are seperate because a credential provider might
// want to set up a credential with various combinations of field state pairs
// and field descriptors.

// The field state value indicates whether the field is displayed
// in the selected tile, the deselected tile, or both.
// The Field interactive state indicates when
static const FIELD_STATE_PAIR s_rgFieldStatePairs[] =
{
    { CPFS_DISPLAY_IN_BOTH,            CPFIS_NONE    },    // SFI_TILEIMAGE
    { CPFS_HIDDEN,                     CPFIS_NONE    },    // SFI_LABEL
    { CPFS_DISPLAY_IN_BOTH,            CPFIS_NONE    },    // SFI_LARGE_TEXT
    { CPFS_DISPLAY_IN_SELECTED_TILE,   CPFIS_FOCUSED },    // SFI_PASSWORD
    { CPFS_DISPLAY_IN_SELECTED_TILE,   CPFIS_NONE    },    // SFI_SUBMIT_BUTTON
    { CPFS_DISPLAY_IN_SELECTED_TILE,   CPFIS_NONE    },    // SFI_LAUNCHWINDOW_LINK
    { CPFS_DISPLAY_IN_SELECTED_TILE,   CPFIS_NONE    },    // SFI_HIDECONTROLS_LINK
    { CPFS_DISPLAY_IN_SELECTED_TILE,   CPFIS_NONE    },    // SFI_FULLNAME_TEXT
    { CPFS_DISPLAY_IN_SELECTED_TILE,   CPFIS_NONE    },    // SFI_DISPLAYNAME_TEXT
    { CPFS_DISPLAY_IN_SELECTED_TILE,   CPFIS_NONE    },    // SFI_LOGONSTATUS_TEXT
    { CPFS_DISPLAY_IN_SELECTED_TILE,   CPFIS_NONE    },    // SFI_CHECKBOX
    { CPFS_DISPLAY_IN_SELECTED_TILE,   CPFIS_NONE    },    // SFI_EDIT_TEXT
    { CPFS_DISPLAY_IN_SELECTED_TILE,   CPFIS_NONE    },    // SFI_COMBOBOX
};

// Field descriptors for unlock and logon.
// The first field is the index of the field.
// The second is the type of the field.
// The third is the name of the field, NOT the value which will appear in the field.
static const CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR s_rgCredProvFieldDescriptors[] =
{
    { SFI_TILEIMAGE,         CPFT_TILE_IMAGE,    L"Image",                      CPFG_CREDENTIAL_PROVIDER_LOGO  },
    { SFI_LABEL,             CPFT_SMALL_TEXT,    L"Tooltip",                    CPFG_CREDENTIAL_PROVIDER_LABEL },
    { SFI_LARGE_TEXT,        CPFT_LARGE_TEXT,    L"Sample Credential Provider"                                 },
    { SFI_PASSWORD,          CPFT_PASSWORD_TEXT, L"Password text"                                              },
    { SFI_SUBMIT_BUTTON,     CPFT_SUBMIT_BUTTON, L"Submit"                                                     },
    { SFI_LAUNCHWINDOW_LINK, CPFT_COMMAND_LINK,  L"Launch helper window"                                       },
    { SFI_HIDECONTROLS_LINK, CPFT_COMMAND_LINK,  L"Hide additional controls"                                   },
    { SFI_FULLNAME_TEXT,     CPFT_SMALL_TEXT,    L"Full name: "                                                },
    { SFI_DISPLAYNAME_TEXT,  CPFT_SMALL_TEXT,    L"Display name: "                                             },
    { SFI_LOGONSTATUS_TEXT,  CPFT_SMALL_TEXT,    L"Logon status: "                                             },
    { SFI_CHECKBOX,          CPFT_CHECKBOX,      L"Checkbox"                                                   },
    { SFI_EDIT_TEXT,         CPFT_EDIT_TEXT,     L"Edit text"                                                  },
    { SFI_COMBOBOX,          CPFT_COMBOBOX,      L"Combobox"                                                   },
};

static const PWSTR s_rgComboBoxStrings[] =
{
    L"First",
    L"Second",
    L"Third",
};

其中,CredentialProvider所提供的部分UI控件样式与展示形式并非完全一成不变,如图中所示的CPFT_SUBMIT_BUTTON按钮可以像图中③那样附属于CPFT_PASSWORD_TEXT控件右侧以向右的箭头形式显示,也可以以独立形式的按钮显示。若以独立的按钮形式显示,则只可在自定义凭据类中对GetSubmitButtonValue方法中的*pdwAdjacentTo参数原来所赋值的CPFT_PASSWORD_TEXT字段ID(SFI_PASSWORD)修改为按钮自身所对应的字段ID(SFI_SUBMIT_BUTTON)即可,并将common.h中CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR中的按钮字段所对应的第四个GUID参数指定为CPFG_STANDALONE_SUBMIT_BUTTON即可,具体代码如下:

// TestCredential.cpp

HRESULT TestCredential::GetSubmitButtonValue(DWORD dwFieldID, _Out_ DWORD *pdwAdjacentTo)
{
    OutputDebugStringA(__FUNCTION__);
    HRESULT hr;

    if (SFI_SUBMIT_BUTTON == dwFieldID)
    {
        // #########################################################################
        // 附属于CPFT_PASSWORD_TEXT密码文本控件,密码文本控件对应的字段ID为SFI_PASSWORD
        //*pdwAdjacentTo = SFI_PASSWORD;
        // #########################################################################

        // #########################################################################
        // 按钮独立显示,则赋值为SFI_SUBMIT_BUTTON
        *pdwAdjacentTo = SFI_SUBMIT_BUTTON;
        // #########################################################################

        hr = S_OK;
    }
    else
    {
        hr = E_INVALIDARG;
    }
    return hr;
}

指定第四个GUID参数为CPFG_STANDALONE_SUBMIT_BUTTON,意思为以标准按钮形式显示,具体如下:

static const CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR s_rgCredProvFieldDescriptors[] =
{
    // 指定第四个参数为CPFG_STANDALONE_SUBMIT_BUTTON,意思为以标准按钮形式显示
    { SFI_SUBMIT_BUTTON, CPFT_SUBMIT_BUTTON, L"Submit", CPFG_STANDALONE_SUBMIT_BUTTON},
};

类似的CPFT_COMMAND_LINK链接文本控件,其可以通过指定第四个GUID参数为CPFG_STYLE_LINK_AS_BUTTON而以标准按钮形式显示,具体代码如下:

static const CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR s_rgCredProvFieldDescriptors[] =
{
    { SFI_HIDECONTROLS_LINK, CPFT_COMMAND_LINK, L"Hide additional controls", PFG_STYLE_LINK_AS_BUTTON},
};

又如上面登录界面图示中的CPFT_SMALL_TEXT小文本控件,其可以以普通的文本形式直接显示,如图中标号⑤;也可以指定第四个参数GUID为CPFG_CREDENTIAL_PROVIDER_LABEL而交互显示于凭据Logo之上,当鼠标置于凭据插件logo上时,根据预设的提示词提示当前凭据类型,具体如图中标号⑨。

除了以上常用的UI显示形式外,CredentialProvrhai还有其它一些UI控件显示形式,更多的UI可选性显示形式定义见如下GUID定义,开发者可以根据研发需要设置相应的GUID进行显示设定

// ShlGuid.h:669

//
// These GUIDs may be assigned to the CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR::guidFieldType
// member by Microsoft ICredentialProvider implementations.
//

// {da15bbe8-954sd-4fd3-b0f4-1fb5b90b174b}
DEFINE_GUID(CPFG_LOGON_USERNAME, 0xda15bbe8, 0x954d, 0x4fd3, 0xb0, 0xf4, 0x1f, 0xb5, 0xb9, 0x0b, 0x17, 0x4b);

// {60624cfa-a477-47b1-8a8e-3a4a19981827}
DEFINE_GUID(CPFG_LOGON_PASSWORD, 0x60624cfa, 0xa477, 0x47b1, 0x8a, 0x8e, 0x3a, 0x4a, 0x19, 0x98, 0x18, 0x27);

// {3e1ecf69-568c-4d96-9d59-46444174e2d6}
DEFINE_GUID(CPFG_SMARTCARD_USERNAME, 0x3e1ecf69, 0x568c, 0x4d96, 0x9d, 0x59, 0x46, 0x44, 0x41, 0x74, 0xe2, 0xd6);

// {4fe5263b-9181-46c1-b0a4-9dedd4db7dea}
DEFINE_GUID(CPFG_SMARTCARD_PIN, 0x4fe5263b, 0x9181, 0x46c1, 0xb0, 0xa4, 0x9d, 0xed, 0xd4, 0xdb, 0x7d, 0xea);

// {2d837775-f6cd-464e-a745-482fd0b47493}
DEFINE_GUID(CPFG_CREDENTIAL_PROVIDER_LOGO, 0x2d837775, 0xf6cd, 0x464e, 0xa7, 0x45, 0x48, 0x2f, 0xd0, 0xb4, 0x74, 0x93);

// {286BBFF3-BAD4-438F-B007-79B7267C3D48}
DEFINE_GUID(CPFG_CREDENTIAL_PROVIDER_LABEL, 0x286bbff3, 0xbad4, 0x438f, 0xb0, 0x7, 0x79, 0xb7, 0x26, 0x7c, 0x3d, 0x48);

// {0b7b0ad8-cc36-4d59-802b-82f714fa7022}
DEFINE_GUID(CPFG_STANDALONE_SUBMIT_BUTTON, 0x0b7b0ad8, 0xcc36, 0x4d59, 0x80, 0x2b, 0x82, 0xf7, 0x14, 0xfa, 0x70, 0x22);

// {088fa508-94a6-4430-a4cb-6fc6e3c0b9e2}
DEFINE_GUID(CPFG_STYLE_LINK_AS_BUTTON, 0x088fa508, 0x94a6, 0x4430, 0xa4, 0xcb, 0x6f, 0xc6, 0xe3, 0xc0, 0xb9, 0xe2);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值