监控屏幕背光Brightness变化的通知

MS网站上给出了用Power Shell的方式用来设置/获取Brightness的值。

为了方便使用,将相关接口进行了封装:

#pragma once

#include 
#include 
#include 
#include 
#include 
#include 
#pragma comment(lib, "wbemuuid.lib")

typedef void (*PFN_CALLBACK)(DWORD dwBrightness, LPVOID lpContext);

class CBrightnessCtrl : public IWbemObjectSink
{
public:
	CBrightnessCtrl(PFN_CALLBACK pCallback, LPVOID lpContext);
	~CBrightnessCtrl(void);

public:
	inline BOOL VerifyValid(void) { return (NULL != this) ? m_bValid : FALSE; }
	BOOL Get(DWORD* pdwValue);
	BOOL Set(DWORD dwValue);

public:
	virtual ULONG STDMETHODCALLTYPE AddRef();
	virtual ULONG STDMETHODCALLTYPE Release();
	virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppv);
	virtual HRESULT STDMETHODCALLTYPE Indicate(LONG lObjectCount, IWbemClassObject __RPC_FAR *__RPC_FAR *apObjArray);
	virtual HRESULT STDMETHODCALLTYPE SetStatus(
		/* [in] */ LONG lFlags,
		/* [in] */ HRESULT hResult,
		/* [in] */ BSTR strParam,
		/* [in] */ IWbemClassObject __RPC_FAR *pObjParam
	);

private:
	BOOL Initialize(void);
	void Uninitialize(void);
	BOOL m_bValid;

private:
	LONG m_lRefCount;

	IWbemLocator* m_pLocator;
	IWbemServices* m_pService;
	IUnsecuredApartment* m_pUnsecuredApartment;
	IUnknown* m_pStubUnkown;
	IWbemObjectSink* m_pStubSink;

	PFN_CALLBACK m_pCallback;
	LPVOID m_pContext;
};
#include "stdafx.h"
#include "BrightnessCtrl.h"


CBrightnessCtrl::CBrightnessCtrl(PFN_CALLBACK pCallback, LPVOID lpContext)
	: m_pCallback(pCallback)
	, m_pContext(lpContext)
	, m_pLocator(NULL)
	, m_pService(NULL)
	, m_pUnsecuredApartment(NULL)
	, m_pStubUnkown(NULL)
	, m_pStubSink(NULL)
	, m_bValid(FALSE)
	, m_lRefCount(1)
{
	_ASSERT(NULL != m_pCallback);
	_ASSERT(NULL != m_pContext);

	Initialize();
}

CBrightnessCtrl::~CBrightnessCtrl(void)
{
	// Uninitialize
	Uninitialize();
}

BOOL CBrightnessCtrl::Get(DWORD* pdwValue)
{
	BOOL bRet = FALSE;

	IEnumWbemClassObject* pEnumerator = NULL;

	do
	{
		if (NULL == pdwValue) { break; }

		if (!m_bValid) { break; }

		_ASSERT(NULL != m_pService);
		if (FAILED(m_pService->ExecQuery(L"WQL", L"SELECT * FROM WmiMonitorBrightness", WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator))) { break; }

		IWbemClassObject *papObject = NULL;

		while (NULL != pEnumerator)
		{
			ULONG uReturned = 0;

			if (FAILED(pEnumerator->Next(WBEM_INFINITE, 1, &papObject, &uReturned)) || ((0 == uReturned))) { break; }

			VARIANT var;
			VariantInit(&var);
			
			if (FAILED(papObject->Get(TEXT("CurrentBrightness"), 0, &var, 0, 0))) { break; }
			
			*pdwValue = (DWORD)var.intVal;
			
			VariantClear(&var);

			bRet = TRUE;
		}

		if (NULL != papObject) { papObject->Release(); papObject = NULL; }

		// Completed
	} while (0);

	if (NULL != pEnumerator) { pEnumerator->Release(); pEnumerator = NULL; }

	return bRet;
}

BOOL CBrightnessCtrl::Set(DWORD dwValue)
{
	BOOL bRet = FALSE;

	IEnumWbemClassObject* pEnumerator = NULL;
	IWbemClassObject * pClsObject = NULL;
	IWbemClassObject * pInSignature = NULL;
	IWbemClassObject * pNewInstance = NULL;

	do
	{
		if (!m_bValid) { break; }

		_ASSERT(NULL != m_pService);
		if (FAILED(m_pService->ExecQuery(L"WQL", L"SELECT * FROM WmiMonitorBrightnessMethods", WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator))) { break; }

		IWbemClassObject *papObject = NULL;

		while (NULL != pEnumerator)
		{
			if (NULL != papObject) {papObject->Release(); papObject = NULL; }

			ULONG ulReturned = 0;
			if (FAILED(pEnumerator->Next(WBEM_INFINITE, 1, &papObject, &ulReturned)) || (0 == ulReturned)) { break; }
			if (FAILED(m_pService->GetObject(L"WmiMonitorBrightnessMethods", 0, NULL, &pClsObject, NULL))) { break; }
			if (FAILED(pClsObject->GetMethod(L"WmiSetBrightness", 0, &pInSignature, NULL))) { break; }
			if (FAILED(pInSignature->SpawnInstance(0, &pNewInstance))) { break; }

			VARIANT var;
			VariantInit(&var);
			V_VT(&var) = VT_BSTR;
			V_BSTR(&var) = SysAllocString(L"0");
			if (FAILED(pNewInstance->Put(L"Timeout", 0, &var, CIM_UINT32))) { VariantClear(&var); break; }

			VariantClear(&var);
			VariantInit(&var);
			V_VT(&var) = VT_I4;
			V_I4(&var) = (INT)dwValue;
			if (FAILED(pNewInstance->Put(L"Brightness", 0, &var, CIM_UINT8))) { VariantClear(&var); break; }
			
			VariantClear(&var);
			VariantInit(&var);
			papObject->Get(L"__PATH", 0, &var, NULL, NULL);

			if (FAILED(m_pService->ExecMethod(var.bstrVal, L"WmiSetBrightness", 0, NULL, pNewInstance, NULL, NULL))) { VariantClear(&var); break; }
			
			VariantClear(&var);
			
			bRet = TRUE;
		}

		if (NULL != papObject) { papObject->Release(); papObject = NULL; }

		// Completed
	} while (0);

	if (NULL != pNewInstance) { pNewInstance->Release(); pNewInstance = NULL; }
	if (NULL != pInSignature) { pInSignature->Release(); pInSignature = NULL; }
	if (NULL != pClsObject) { pClsObject->Release(); pClsObject = NULL; }
	if (NULL != pEnumerator) { pEnumerator->Release(); pEnumerator = NULL; }

	return bRet;
}

BOOL CBrightnessCtrl::Initialize(void)
{
	// Initialize COM
	CoInitializeEx(NULL, COINIT_MULTITHREADED);

	do
	{
		if (m_bValid) { break; }

		HRESULT hRet = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
		if ((S_OK != hRet) && (RPC_E_TOO_LATE != hRet)) { break; }

		if (FAILED(CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *)&m_pLocator))) { break; }
		if (FAILED(m_pLocator->ConnectServer(L"ROOT\\WMI", NULL, NULL, 0, NULL, 0, 0, &m_pService))) { break; }
		if (FAILED(CoSetProxyBlanket(m_pService, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE))) { break; }
		if (FAILED(CoCreateInstance(CLSID_UnsecuredApartment, NULL, CLSCTX_LOCAL_SERVER, IID_IUnsecuredApartment, (void**)&m_pUnsecuredApartment))) { break; }
		if (FAILED(m_pUnsecuredApartment->CreateObjectStub(this, &m_pStubUnkown))) { break; }
		if (FAILED(m_pStubUnkown->QueryInterface(IID_IWbemObjectSink, (void **)&m_pStubSink))) { break; }
		if (FAILED(m_pService->ExecNotificationQueryAsync(L"WQL", L"SELECT * FROM WmiMonitorBrightnessEvent", WBEM_FLAG_SEND_STATUS, NULL, m_pStubSink))) { break; }

		// Completed
		m_bValid = TRUE;
	} while (0);

	return m_bValid;
}

void CBrightnessCtrl::Uninitialize(void)
{
	if ((NULL != m_pService) && (NULL != m_pStubSink)) { m_pService->CancelAsyncCall(m_pStubSink); }

	if (NULL != m_pStubSink) { m_pStubSink->Release(); m_pStubSink = NULL; }
	if (NULL != m_pStubUnkown) { m_pStubUnkown->Release(); m_pStubUnkown = NULL; }
	if (NULL != m_pUnsecuredApartment) { m_pUnsecuredApartment->Release(); m_pUnsecuredApartment = NULL; }
	if (NULL != m_pLocator) { m_pLocator->Release(); m_pLocator = NULL; }
	if (NULL != m_pService) { m_pService->Release(); m_pService = NULL; }

	// Uninitialize COM
	CoUninitialize();
}

ULONG CBrightnessCtrl::AddRef()
{
	return InterlockedIncrement(&m_lRefCount);
}

ULONG CBrightnessCtrl::Release()
{
	ULONG lRef = 0;

	do
	{
		if (0 == m_lRefCount) { break; }

		lRef = InterlockedDecrement(&m_lRefCount);

		if (0 == lRef) { delete this; }

		// Completed
	} while (0);

	return lRef;
}

HRESULT CBrightnessCtrl::QueryInterface(REFIID riid, void** ppv)
{
	if ((IID_IUnknown == riid) || (IID_IWbemObjectSink == riid))
	{
		*ppv = (IWbemObjectSink*) this;

		AddRef();

		return WBEM_S_NO_ERROR;
	}

	return E_NOINTERFACE;
}

HRESULT CBrightnessCtrl::Indicate(LONG lObjectCount, IWbemClassObject __RPC_FAR *__RPC_FAR *pObjArray)
{
	HRESULT hRet = WBEM_E_FAILED;

	do
	{
		if (NULL == pObjArray) { break; }

		for (LONG i = 0; i < lObjectCount; i++)
		{
			VARIANT var;
			VariantInit(&var);

			if ((NULL == pObjArray[i]) || FAILED(pObjArray[i]->Get(L"Brightness", 0, &var, NULL, NULL))) { break; }

			if (NULL != m_pCallback) { m_pCallback(var.intVal, m_pContext); }

			VariantClear(&var);

			hRet = WBEM_S_NO_ERROR;
			break;
		}

		// Completed
	} while (0);

	return hRet;
}

HRESULT CBrightnessCtrl::SetStatus(
	/* [in] */ LONG lFlags,
	/* [in] */ HRESULT hResult,
	/* [in] */ BSTR strParam,
	/* [in] */ IWbemClassObject __RPC_FAR *pObjParam
)
{
	UNREFERENCED_PARAMETER(lFlags);
	UNREFERENCED_PARAMETER(hResult);
	UNREFERENCED_PARAMETER(strParam);
	UNREFERENCED_PARAMETER(pObjParam);

	return WBEM_S_NO_ERROR;
}


调用比较简单,如下所示:
CBrightnessCtrl* pBrightnessCtrl = new CBrightnessCtrl(BrightnessCallback, NULL);
ASSERT(NULL != pBrightnessCtrl);

// Get Brightness
DWORD dwValue = 0;
pBrightenssCtrl->Get(&dwValue);

// Set Brightness
dwValue = 75;
pBrightnessCtrl->Set(dwValue);

// Callback
void BrightnessCallback(DWORD dwBrightness, LPVOID lpContext)
{
   CString strText(TEXT(""));   
   strText.Format(TEXT("Brightness: %u"), dwBrightness);      
   AfxMessageBox(strText);
}








你可能感兴趣的:(VC/MFC,Development)