Added Aero blur support. Documentation available at: http://rainmeter.net/RainCMS/?q=Skins_AeroBlur_beta

This commit is contained in:
Birunthan Mohanathas 2011-04-08 18:14:32 +00:00
parent b92d8276d3
commit a9c0b76c2c
5 changed files with 454 additions and 20 deletions

View File

@ -47,6 +47,12 @@ using namespace Gdiplus;
int CMeterWindow::c_InstanceCount = 0;
HINSTANCE CMeterWindow::c_DwmInstance = NULL;
FPDWMENABLEBLURBEHINDWINDOW CMeterWindow::c_DwmEnableBlurBehindWindow = NULL;
FPDWMGETCOLORIZATIONCOLOR CMeterWindow::c_DwmGetColorizationColor = NULL;
FPDWMSETWINDOWATTRIBUTE CMeterWindow::c_DwmSetWindowAttribute = NULL;
FPDWMISCOMPOSITIONENABLED CMeterWindow::c_DwmIsCompositionEnabled = NULL;
extern CRainmeter* Rainmeter;
/*
@ -112,6 +118,9 @@ CMeterWindow::CMeterWindow(const std::wstring& path, const std::wstring& config,
m_BackgroundMode(BGMODE_IMAGE),
m_SolidAngle(),
m_SolidBevel(BEVELTYPE_NONE),
m_Blur(false),
m_BlurMode(BLURMODE_NONE),
m_BlurRegion(),
m_FadeStartTime(),
m_FadeStartValue(),
m_FadeEndValue(),
@ -126,6 +135,18 @@ CMeterWindow::CMeterWindow(const std::wstring& path, const std::wstring& config,
m_MouseActionCursor(true),
m_ToolTipHidden(false)
{
if (!c_DwmInstance && CSystem::GetOSPlatform() >= OSPLATFORM_VISTA)
{
c_DwmInstance = CSystem::RmLoadLibrary(L"dwmapi.dll");
if (c_DwmInstance)
{
c_DwmEnableBlurBehindWindow = (FPDWMENABLEBLURBEHINDWINDOW)GetProcAddress(c_DwmInstance, "DwmEnableBlurBehindWindow");
c_DwmGetColorizationColor = (FPDWMGETCOLORIZATIONCOLOR)GetProcAddress(c_DwmInstance, "DwmGetColorizationColor");
c_DwmSetWindowAttribute = (FPDWMSETWINDOWATTRIBUTE)GetProcAddress(c_DwmInstance, "DwmSetWindowAttribute");
c_DwmIsCompositionEnabled = (FPDWMISCOMPOSITIONENABLED)GetProcAddress(c_DwmInstance, "DwmIsCompositionEnabled");
}
}
++c_InstanceCount;
}
@ -163,6 +184,8 @@ CMeterWindow::~CMeterWindow()
if (m_DoubleBuffer) delete m_DoubleBuffer;
if (m_DIBSectionBuffer) DeleteObject(m_DIBSectionBuffer);
if (m_BlurRegion) DeleteObject(m_BlurRegion);
if (m_Window) DestroyWindow(m_Window);
if (m_FontCollection)
@ -183,6 +206,17 @@ CMeterWindow::~CMeterWindow()
Sleep(100);
++counter;
} while(!Result && counter < 10);
if (c_DwmInstance)
{
FreeLibrary(c_DwmInstance);
c_DwmInstance = NULL;
c_DwmEnableBlurBehindWindow = NULL;
c_DwmGetColorizationColor = NULL;
c_DwmSetWindowAttribute = NULL;
c_DwmIsCompositionEnabled = NULL;
}
}
}
@ -271,22 +305,10 @@ int CMeterWindow::Initialize(CRainmeter& Rainmeter)
*/
void CMeterWindow::IgnoreAeroPeek()
{
typedef HRESULT (WINAPI * FPDWMSETWINDOWATTRIBUTE)(HWND hwnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute);
#define DWMWA_EXCLUDED_FROM_PEEK 12
if (CSystem::GetOSPlatform() >= OSPLATFORM_VISTA)
if (c_DwmSetWindowAttribute)
{
HINSTANCE h = CSystem::RmLoadLibrary(L"dwmapi.dll");
if (h)
{
FPDWMSETWINDOWATTRIBUTE DwmSetWindowAttribute = (FPDWMSETWINDOWATTRIBUTE)GetProcAddress(h, "DwmSetWindowAttribute");
if (DwmSetWindowAttribute)
{
BOOL bValue = TRUE;
DwmSetWindowAttribute(m_Window, DWMWA_EXCLUDED_FROM_PEEK, &bValue, sizeof(bValue));
}
FreeLibrary(h);
}
BOOL bValue = TRUE;
c_DwmSetWindowAttribute(m_Window, DWMWA_EXCLUDED_FROM_PEEK, &bValue, sizeof(bValue));
}
}
@ -346,6 +368,9 @@ void CMeterWindow::Refresh(bool init, bool all)
m_BackgroundName.erase();
if (m_BlurRegion) DeleteObject(m_BlurRegion);
m_BlurRegion = NULL;
if (m_FontCollection)
{
CMeterString::FreeFontCache(m_FontCollection);
@ -411,6 +436,15 @@ void CMeterWindow::Refresh(bool init, bool all)
ChangeZPos(m_WindowZPosition, all);
}
if (m_BlurMode == BLURMODE_NONE)
{
HideBlur();
}
else
{
ShowBlur();
}
m_Rainmeter->SetCurrentParser(NULL);
m_Refreshing = false;
@ -670,6 +704,28 @@ void CMeterWindow::RunBang(BANGCOMMAND bang, const WCHAR* arg)
}
break;
case BANG_SHOWBLUR:
ShowBlur();
break;
case BANG_HIDEBLUR:
HideBlur();
break;
case BANG_TOGGLEBLUR:
RunBang(IsBlur() ? BANG_HIDEBLUR : BANG_SHOWBLUR, arg);
break;
case BANG_ADDBLUR:
ResizeBlur(arg, RGN_OR);
if (IsBlur()) ShowBlur();
break;
case BANG_REMOVEBLUR:
ResizeBlur(arg, RGN_DIFF);
if (IsBlur()) ShowBlur();
break;
case BANG_TOGGLEMETER:
ToggleMeter(arg);
break;
@ -961,6 +1017,142 @@ bool CompareName(T* m, const WCHAR* name, bool group)
return (group) ? m->BelongsToGroup(name) : (_wcsicmp(m->GetName(), name) == 0);
}
/*
** ShowBlur
**
** Enables blurring of the window background (using Aero)
**
*/
void CMeterWindow::ShowBlur()
{
if (c_DwmGetColorizationColor && c_DwmIsCompositionEnabled && c_DwmEnableBlurBehindWindow)
{
SetBlur(true);
// Check that Aero and transparency is enabled
DWORD color;
BOOL opaque, enabled;
if (c_DwmGetColorizationColor(&color, &opaque) != S_OK)
{
opaque = TRUE;
}
if (c_DwmIsCompositionEnabled(&enabled) != S_OK)
{
enabled = FALSE;
}
if (opaque || !enabled) return;
if (m_BlurMode == BLURMODE_FULL)
{
if (m_BlurRegion) DeleteObject(m_BlurRegion);
m_BlurRegion = CreateRectRgn(0, 0, GetW(), GetH());
}
BlurBehindWindow(TRUE);
}
}
/*
** HideBlur
**
** Disables Aero blur
**
*/
void CMeterWindow::HideBlur()
{
if (c_DwmEnableBlurBehindWindow)
{
SetBlur(false);
BlurBehindWindow(FALSE);
}
}
/*
** ResizeBlur
**
** Adds to or removes from blur region
**
*/
void CMeterWindow::ResizeBlur(const WCHAR* arg, int mode)
{
if (CSystem::GetOSPlatform() >= OSPLATFORM_VISTA)
{
WCHAR* parseSz = _wcsdup(arg);
double val;
int type, x, y, w, h;
WCHAR* token = wcstok(parseSz, L",");
if (token)
{
while (token[0] == L' ') ++token;
type = (m_Parser.ReadFormula(token, &val) == 1) ? (int)val : _wtoi(token);
}
token = wcstok(NULL, L",");
if (token)
{
while (token[0] == L' ') ++token;
x = (m_Parser.ReadFormula(token, &val) == 1) ? (int)val : _wtoi(token);
}
token = wcstok(NULL, L",");
if (token)
{
while (token[0] == L' ') ++token;
y = (m_Parser.ReadFormula(token, &val) == 1) ? (int)val : _wtoi(token);
}
token = wcstok(NULL, L",");
if (token)
{
while (token[0] == L' ') ++token;
w = (m_Parser.ReadFormula(token, &val) == 1) ? (int)val : _wtoi(token);
}
token = wcstok(NULL, L",");
if (token)
{
while (token[0] == L' ') ++token;
h = (m_Parser.ReadFormula(token, &val) == 1) ? (int)val : _wtoi(token);
}
if (w && h)
{
HRGN tempRegion;
switch (type)
{
case 1:
tempRegion = CreateRectRgn(x, y, w, h);
break;
case 2:
token = wcstok(NULL, L",");
if (token)
{
while (token[0] == L' ') ++token;
int r = (m_Parser.ReadFormula(token, &val) == 1) ? (int)val : _wtoi(token);
tempRegion = CreateRoundRectRgn(x, y, w, h, r, r);
}
break;
case 3:
tempRegion = CreateEllipticRgn(x, y, w, h);
break;
default: // Unknown type
free(parseSz);
return;
}
CombineRgn(m_BlurRegion, m_BlurRegion, tempRegion, mode);
DeleteObject(tempRegion);
}
free(parseSz);
}
}
/*
** ShowMeter
**
@ -1832,14 +2024,49 @@ bool CMeterWindow::ReadSkin()
m_MouseActionCursor = 0 != m_Parser.ReadInt(L"Rainmeter", L"MouseActionCursor", 1);
m_ToolTipHidden = 0 != m_Parser.ReadInt(L"Rainmeter", L"ToolTipHidden", 0);
if (CSystem::GetOSPlatform() >= OSPLATFORM_VISTA)
{
if (0 != m_Parser.ReadInt(L"Rainmeter", L"Blur", 0))
{
std::wstring blurRegion = m_Parser.ReadString(L"Rainmeter", L"BlurRegion", L"", false);
if (!blurRegion.empty())
{
m_BlurMode = BLURMODE_REGION;
m_BlurRegion = CreateRectRgn(0, 0, 0, 0); // Create empty region
int i = 1;
do
{
ResizeBlur(blurRegion.c_str(), RGN_OR);
// Here we are checking to see if there are more than one blur region
// to be loaded. They will be named BlurRegion2, BlurRegion3, etc.
WCHAR tmpName[64];
_snwprintf_s(tmpName, _TRUNCATE, L"BlurRegion%i", ++i);
blurRegion = m_Parser.ReadString(L"Rainmeter", tmpName, L"");
} while (!blurRegion.empty());
}
else
{
m_BlurMode = BLURMODE_FULL;
}
}
else
{
m_BlurMode = BLURMODE_NONE;
}
}
// Checking for localfonts
std::wstring localFont = m_Parser.ReadString(L"Rainmeter", L"LocalFont", L"");
// If there is a local font we want to load it
if (!localFont.empty())
{
m_FontCollection = new PrivateFontCollection();
int i = 1;
int i = 2;
do
{
// We want to check the fonts folder first
@ -1875,7 +2102,7 @@ bool CMeterWindow::ReadSkin()
// Here we are checking to see if there are more than one local font
// to be loaded. They will be named LocalFont2, LocalFont3, etc.
WCHAR tmpName[64];
_snwprintf_s(tmpName, _TRUNCATE, L"LocalFont%i", i++);
_snwprintf_s(tmpName, _TRUNCATE, L"LocalFont%i", ++i);
localFont = m_Parser.ReadString(L"Rainmeter", tmpName, L"");
} while (!localFont.empty());
@ -3808,6 +4035,80 @@ LRESULT CMeterWindow::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam)
return 0;
}
/*
** OnDwmColorChange
**
** Disables blur when Aero transparency is disabled
**
*/
LRESULT CMeterWindow::OnDwmColorChange(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (m_BlurMode != BLURMODE_NONE && IsBlur() && c_DwmGetColorizationColor && c_DwmEnableBlurBehindWindow)
{
DWORD color;
BOOL opaque;
if (c_DwmGetColorizationColor(&color, &opaque) != S_OK)
{
opaque = TRUE;
}
BlurBehindWindow(!opaque);
}
return 0;
}
/*
** OnDwmCompositionChange
**
** Disables blur when desktop composition is disabled
**
*/
LRESULT CMeterWindow::OnDwmCompositionChange(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (m_BlurMode != BLURMODE_NONE && IsBlur() && c_DwmIsCompositionEnabled && c_DwmEnableBlurBehindWindow)
{
BOOL enabled;
if (c_DwmIsCompositionEnabled(&enabled) != S_OK)
{
enabled = FALSE;
}
BlurBehindWindow(enabled);
}
return 0;
}
/*
** BlurBehindWindow
**
** Adds the blur region to the window
**
*/
void CMeterWindow::BlurBehindWindow(BOOL fEnable)
{
if (c_DwmEnableBlurBehindWindow)
{
DWM_BLURBEHIND bb = {0};
bb.fEnable = fEnable;
if (fEnable)
{
// Restore blur with whatever the region was prior to disabling
bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
bb.hRgnBlur = m_BlurRegion;
c_DwmEnableBlurBehindWindow(m_Window, &bb);
}
else
{
// Disable blur
bb.dwFlags = DWM_BB_ENABLE;
c_DwmEnableBlurBehindWindow(m_Window, &bb);
}
}
}
/*
** OnDisplayChange
**
@ -4578,6 +4879,8 @@ LRESULT CALLBACK CMeterWindow::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
MESSAGE(OnDelayedExecute, WM_DELAYED_EXECUTE)
MESSAGE(OnDelayedRefresh, WM_DELAYED_REFRESH)
MESSAGE(OnDelayedMove, WM_DELAYED_MOVE)
MESSAGE(OnDwmColorChange, WM_DWMCOLORIZATIONCOLORCHANGED)
MESSAGE(OnDwmCompositionChange, WM_DWMCOMPOSITIONCHANGED)
MESSAGE(OnSettingChange, WM_SETTINGCHANGE)
MESSAGE(OnDisplayChange, WM_DISPLAYCHANGE)
END_MESSAGEPROC

View File

@ -22,6 +22,7 @@
#include <windows.h>
#include <gdiplus.h>
#include <dwmapi.h>
#include <string>
#include <list>
#include "ConfigParser.h"
@ -38,6 +39,11 @@
#define METERWINDOW_CLASS_NAME L"RainmeterMeterWindow"
typedef HRESULT (WINAPI * FPDWMENABLEBLURBEHINDWINDOW)(HWND hWnd, const DWM_BLURBEHIND* pBlurBehind);
typedef HRESULT (WINAPI * FPDWMGETCOLORIZATIONCOLOR)(DWORD* pcrColorization, BOOL* pfOpaqueBlend);
typedef HRESULT (WINAPI * FPDWMSETWINDOWATTRIBUTE)(HWND hwnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute);
typedef HRESULT (WINAPI * FPDWMISCOMPOSITIONENABLED)(BOOL* pfEnabled);
enum MOUSE
{
MOUSE_LMB_DOWN,
@ -69,6 +75,13 @@ enum ZPOSITION
ZPOSITION_ONTOPMOST = 2
};
enum BLURMODE
{
BLURMODE_NONE = 0,
BLURMODE_FULL,
BLURMODE_REGION
};
enum BGMODE
{
BGMODE_IMAGE = 0,
@ -107,6 +120,11 @@ enum BANGCOMMAND
BANG_ENABLEMEASURE,
BANG_DISABLEMEASURE,
BANG_UPDATEMEASURE,
BANG_SHOWBLUR,
BANG_HIDEBLUR,
BANG_TOGGLEBLUR,
BANG_ADDBLUR,
BANG_REMOVEBLUR,
BANG_SHOW,
BANG_HIDE,
BANG_TOGGLE,
@ -170,6 +188,10 @@ public:
void ChangeZPos(ZPOSITION zPos, bool all = false);
void FadeWindow(int from, int to);
void ResizeBlur(const WCHAR* arg, int mode);
bool IsBlur() { return m_Blur; }
void SetBlur(bool b) { m_Blur = b; }
Gdiplus::Bitmap* GetDoubleBuffer() { return m_DoubleBuffer; }
HWND GetWindow() { return m_Window; }
@ -254,6 +276,8 @@ protected:
LRESULT OnDelayedExecute(UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT OnDelayedRefresh(UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT OnDelayedMove(UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT OnDwmColorChange(UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT OnDwmCompositionChange(UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT OnSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT OnDisplayChange(UINT uMsg, WPARAM wParam, LPARAM lParam);
@ -289,9 +313,13 @@ private:
bool DoMoveAction(int x, int y, MOUSE mouse);
bool ResizeWindow(bool reset);
void IgnoreAeroPeek();
void BlurBehindWindow(BOOL fEnable);
void SetWindowPositionVariables(int x, int y);
void SetWindowSizeVariables(int w, int h);
void ShowBlur();
void HideBlur();
void CreateDoubleBuffer(int cx, int cy);
CConfigParser m_Parser;
@ -374,9 +402,13 @@ private:
BGMODE m_BackgroundMode; // The background mode
Gdiplus::Color m_SolidColor; // Color of the solid background
Gdiplus::Color m_SolidColor2; // Color of the solid background
Gdiplus::REAL m_SolidAngle; //
Gdiplus::REAL m_SolidAngle; //
BEVELTYPE m_SolidBevel; // The type of the bevel
bool m_Blur; // If true, Aero blur is active
BLURMODE m_BlurMode; // The blur mode
HRGN m_BlurRegion; // Handle to the blur region
DWORD m_FadeStartTime;
int m_FadeStartValue;
int m_FadeEndValue;
@ -406,6 +438,13 @@ private:
bool m_ToolTipHidden;
static int c_InstanceCount;
static HINSTANCE c_DwmInstance;
static FPDWMENABLEBLURBEHINDWINDOW c_DwmEnableBlurBehindWindow;
static FPDWMGETCOLORIZATIONCOLOR c_DwmGetColorizationColor;
static FPDWMSETWINDOWATTRIBUTE c_DwmSetWindowAttribute;
static FPDWMISCOMPOSITIONENABLED c_DwmIsCompositionEnabled;
};
#endif

View File

@ -549,6 +549,62 @@ void RainmeterToggleFade(HWND, const char* arg)
BangWithArgs(BANG_TOGGLEFADE, ConvertToWide(arg).c_str(), 0);
}
/*
** RainmeterHideBlur
**
** Callback for the !RainmeterHideBlur bang
**
*/
void RainmeterHideBlur(HWND, const char* arg)
{
BangWithArgs(BANG_HIDEBLUR, ConvertToWide(arg).c_str(), 0);
}
/*
** RainmeterShowBlur
**
** Callback for the !RainmeterShowBlur bang
**
*/
void RainmeterShowBlur(HWND, const char* arg)
{
BangWithArgs(BANG_SHOWBLUR, ConvertToWide(arg).c_str(), 0);
}
/*
** RainmeterToggleBlur
**
** Callback for the !RainmeterToggleBlur bang
**
*/
void RainmeterToggleBlur(HWND, const char* arg)
{
BangWithArgs(BANG_TOGGLEBLUR, ConvertToWide(arg).c_str(), 0);
}
/*
** RainmeterAddBlur
**
** Callback for the !RainmeterAddBlur bang
**
*/
void RainmeterAddBlur(HWND, const char* arg)
{
BangWithArgs(BANG_ADDBLUR, ConvertToWide(arg).c_str(), 1);
}
/*
** RainmeterRemoveBlur
**
** Callback for the !RainmeterRemoveBlur bang
**
*/
void RainmeterRemoveBlur(HWND, const char* arg)
{
BangWithArgs(BANG_REMOVEBLUR, ConvertToWide(arg).c_str(), 1);
}
/*
** RainmeterHideMeter
**
@ -1941,6 +1997,11 @@ int CRainmeter::Initialize(HWND Parent, HINSTANCE Instance, LPCSTR szPath)
AddBangCommand("!RainmeterHideFade", RainmeterHideFade);
AddBangCommand("!RainmeterShowFade", RainmeterShowFade);
AddBangCommand("!RainmeterToggleFade", RainmeterToggleFade);
AddBangCommand("!RainmeterHideBlur", RainmeterHideBlur);
AddBangCommand("!RainmeterShowBlur", RainmeterShowBlur);
AddBangCommand("!RainmeterToggleBlur", RainmeterToggleBlur);
AddBangCommand("!RainmeterAddBlur", RainmeterAddBlur);
AddBangCommand("!RainmeterRemoveBlur", RainmeterRemoveBlur);
AddBangCommand("!RainmeterHideMeter", RainmeterHideMeter);
AddBangCommand("!RainmeterShowMeter", RainmeterShowMeter);
AddBangCommand("!RainmeterToggleMeter", RainmeterToggleMeter);
@ -2549,6 +2610,11 @@ void CRainmeter::Quit(HINSTANCE dllInst)
RemoveBangCommand("!RainmeterHideFade");
RemoveBangCommand("!RainmeterShowFade");
RemoveBangCommand("!RainmeterToggleFade");
RemoveBangCommand("!RainmeterHideBlur");
RemoveBangCommand("!RainmeterShowBlur");
RemoveBangCommand("!RainmeterToggleBlur");
RemoveBangCommand("!RainmeterAddBlur");
RemoveBangCommand("!RainmeterRemoveBlur");
RemoveBangCommand("!RainmeterHideMeter");
RemoveBangCommand("!RainmeterShowMeter");
RemoveBangCommand("!RainmeterToggleMeter");
@ -2821,6 +2887,26 @@ BOOL CRainmeter::ExecuteBang(const std::wstring& bang, const std::wstring& arg,
{
BangWithArgs(BANG_UPDATEMEASURE, arg.c_str(), 1);
}
else if (_wcsicmp(bang.c_str(), L"!RainmeterShowBlur") == 0)
{
BangWithArgs(BANG_SHOWBLUR, arg.c_str(), 0);
}
else if (_wcsicmp(bang.c_str(), L"!RainmeterHideBlur") == 0)
{
BangWithArgs(BANG_HIDEBLUR, arg.c_str(), 0);
}
else if (_wcsicmp(bang.c_str(), L"!RainmeterToggleBlur") == 0)
{
BangWithArgs(BANG_TOGGLEBLUR, arg.c_str(), 0);
}
else if (_wcsicmp(bang.c_str(), L"!RainmeterAddBlur") == 0)
{
BangWithArgs(BANG_ADDBLUR, arg.c_str(), 1);
}
else if (_wcsicmp(bang.c_str(), L"!RainmeterRemoveBlur") == 0)
{
BangWithArgs(BANG_REMOVEBLUR, arg.c_str(), 1);
}
else if (_wcsicmp(bang.c_str(), L"!RainmeterActivateConfig") == 0)
{
RainmeterActivateConfigWide(arg.c_str());

View File

@ -47,6 +47,11 @@ void RainmeterToggle(HWND, const char* arg);
void RainmeterShowFade(HWND, const char* arg);
void RainmeterHideFade(HWND, const char* arg);
void RainmeterToggleFade(HWND, const char* arg);
void RainmeterShowBlur(HWND, const char* arg);
void RainmeterHideBlur(HWND, const char* arg);
void RainmeterToggleBlur(HWND, const char* arg);
void RainmeterAddBlur(HWND, const char* arg);
void RainmeterRemoveBlur(HWND, const char* arg);
void RainmeterShowMeter(HWND, const char* arg);
void RainmeterHideMeter(HWND, const char* arg);
void RainmeterToggleMeter(HWND, const char* arg);

View File

@ -30,6 +30,7 @@
#include <ws2tcpip.h>
#include <windows.h>
#include <gdiplus.h>
#include <dwmapi.h>
#include <comdef.h>
#include <Iphlpapi.h>
#include <commctrl.h>