#pragma comment(lib, "comctl32.lib")
#include <stdio.h>
#include <tchar.h>
#include <time.h>
#include <Windows.h>
#include <CommCtrl.h>
#include "resource.h"
#define SEC_GEN _T("General")
#define SEC_FONT _T("Font")
// 関数プロトタイプ宣言
int GetIniFileName(void);
INT_PTR CALLBACK DialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
void OnInitDialog(HWND hDlg);
void OnDestroy(HWND hDlg);
void WriteIniFileInt(TCHAR* ptcSec, TCHAR* ptcKey, int iValue);
void OnButtonFont(HWND hWnd);
void MyChooseColor(HWND hWnd, COLORREF& crResult);
void OnNotify(HWND hDlg, int idCtrl, LPNMUPDOWN pnmud);
int MyRegisterClass(void);
int CreatePanel(HWND hWndParent);
void InitPanel(void);
void DestroyPanel(void);
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void OnDestroyWnd(HWND hWnd);
void OnPaint(HWND hWnd);
// グローバル変数
HINSTANCE g_hInstance;
TCHAR g_atcIniFile[_MAX_PATH] = _T("");
TCHAR g_atcClassName[] = _T("LayeredWnd");
HWND g_hPanel = NULL;
int g_iPanelX;
int g_iPanelY;
LOGFONT g_lf;
HFONT g_hFont = NULL;
COLORREF g_crText; // 文字色
COLORREF g_crBorder; // 縁取り色
int g_iBorder; // 縁取り幅
UINT g_uiIDEvent = 0;
//==============================================================================
int APIENTRY _tWinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
g_hInstance = hInstance;
if (GetIniFileName()) {
return 0;
}
if (MyRegisterClass()) {
return 0;
}
DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAIN_DIALOG), NULL, DialogProc);
return 0;
}
//------------------------------------------------------------------------------
int GetIniFileName(void)
{
TCHAR atcPath [_MAX_PATH];
TCHAR atcDrive[_MAX_DRIVE];
TCHAR atcDir [_MAX_DIR];
TCHAR atcFName[_MAX_FNAME];
TCHAR atcExt [_MAX_EXT];
if (GetModuleFileName(NULL, atcPath, _countof(atcPath)) == 0) {
return -1;
}
if (_tsplitpath_s(atcPath, atcDrive, atcDir, atcFName, atcExt) != 0) {
return -1;
}
if (_tmakepath_s(g_atcIniFile, atcDrive, atcDir, atcFName, _T("ini")) != 0) {
return -1;
}
return 0;
}
//------------------------------------------------------------------------------
INT_PTR CALLBACK DialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
INT_PTR iRetVal = TRUE; // メッセージを処理した
switch (uMsg) {
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDC_BUTTON_PANEL:
if (g_hPanel == NULL) {
CreatePanel(hDlg);
} else {
DestroyPanel();
}
break;
case IDC_BUTTON_FONT:
OnButtonFont(hDlg);
break;
case IDC_BUTTON_TEXT:
MyChooseColor(hDlg, g_crText);
break;
case IDC_BUTTON_BORDER:
MyChooseColor(hDlg, g_crBorder);
break;
}
break;
case WM_NOTIFY:
OnNotify(hDlg, wParam, (LPNMUPDOWN)lParam);
break;
case WM_INITDIALOG:
OnInitDialog(hDlg);
iRetVal = TRUE; // SetFocusでフォーカスを設定した場合はFALSE
break;
case WM_CLOSE:
EndDialog(hDlg, 0);
break;
case WM_DESTROY:
OnDestroy(hDlg);
break;
default:
iRetVal = FALSE; // メッセージを処理しなかった
}
return iRetVal;
}
//------------------------------------------------------------------------------
void OnInitDialog(HWND hDlg)
{
int iMainX;
int iMainY;
InitCommonControls();
// 汎用
iMainX = GetPrivateProfileInt(SEC_GEN, _T("iMainX"), 0, g_atcIniFile);
iMainY = GetPrivateProfileInt(SEC_GEN, _T("iMainY"), 0, g_atcIniFile);
g_iPanelX = GetPrivateProfileInt(SEC_GEN, _T("iPanelX"), 0, g_atcIniFile);
g_iPanelY = GetPrivateProfileInt(SEC_GEN, _T("iPanelY"), 0, g_atcIniFile);
g_crText = GetPrivateProfileInt(SEC_GEN, _T("crText"), 0, g_atcIniFile);
g_crBorder = GetPrivateProfileInt(SEC_GEN, _T("crBorder"), 0, g_atcIniFile);
g_iBorder = GetPrivateProfileInt(SEC_GEN, _T("iBorder"), 2, g_atcIniFile);
// フォント
ZeroMemory(&g_lf, sizeof g_lf);
g_lf.lfHeight = GetPrivateProfileInt(SEC_FONT, _T("Height"), -18, g_atcIniFile);;
GetPrivateProfileString(SEC_FONT, _T("FaceName"), _T("System"),
g_lf.lfFaceName, _countof(g_lf.lfFaceName), g_atcIniFile);
SetWindowPos(hDlg, HWND_TOP, iMainX, iMainY, 0, 0, SWP_NOSIZE);
SetDlgItemInt(hDlg, IDC_EDIT_BORDER, g_iBorder, FALSE);
SendMessage(GetDlgItem(hDlg, IDC_SPIN_BORDER), UDM_SETBUDDY,
(WPARAM)GetDlgItem(hDlg, IDC_EDIT_BORDER), 0);
}
//------------------------------------------------------------------------------
void OnDestroy(HWND hDlg)
{
RECT rc;
DeleteObject(g_hFont);
DestroyPanel();
// 汎用
GetWindowRect(hDlg, &rc);
WriteIniFileInt(SEC_GEN, _T("iMainX"), rc.left);
WriteIniFileInt(SEC_GEN, _T("iMainY"), rc.top);
WriteIniFileInt(SEC_GEN, _T("iPanelX"), g_iPanelX);
WriteIniFileInt(SEC_GEN, _T("iPanelY"), g_iPanelY);
WriteIniFileInt(SEC_GEN, _T("crText"), g_crText);
WriteIniFileInt(SEC_GEN, _T("crBorder"), g_crBorder);
WriteIniFileInt(SEC_GEN, _T("iBorder"), g_iBorder);
// フォント
WriteIniFileInt(SEC_FONT, _T("Height"), g_lf.lfHeight);
WritePrivateProfileString(SEC_FONT, _T("FaceName"), g_lf.lfFaceName, g_atcIniFile);
}
//------------------------------------------------------------------------------
void WriteIniFileInt(TCHAR* ptcSec, TCHAR* ptcKey, int iValue)
{
TCHAR atcBuf[16];
_stprintf_s(atcBuf, _T("%d"), iValue);
WritePrivateProfileString(ptcSec, ptcKey, atcBuf, g_atcIniFile);
}
//------------------------------------------------------------------------------
// フォントボタン
void OnButtonFont(HWND hWnd)
{
CHOOSEFONT cf;
ZeroMemory(&cf, sizeof cf);
cf.lStructSize = sizeof cf;
cf.hwndOwner = hWnd;
cf.lpLogFont = &g_lf;
cf.Flags = CF_SCREENFONTS | CF_INITTOLOGFONTSTRUCT;
cf.nFontType = SCREEN_FONTTYPE;
if (ChooseFont(&cf) == FALSE) {
return;
}
InitPanel();
}
//------------------------------------------------------------------------------
void MyChooseColor(HWND hWnd, COLORREF& crResult)
{
static COLORREF s_acrCust[16];
CHOOSECOLOR cc;
ZeroMemory(&cc, sizeof cc);
cc.lStructSize = sizeof cc;
cc.hwndOwner = hWnd;
cc.rgbResult = crResult;
cc.lpCustColors = s_acrCust;
cc.Flags = CC_RGBINIT;
if (ChooseColor(&cc) == FALSE) {
return;
}
crResult = cc.rgbResult;
}
//------------------------------------------------------------------------------
void OnNotify(HWND hDlg, int idCtrl, LPNMUPDOWN pnmud)
{
int iBorder;
if (idCtrl == IDC_SPIN_BORDER) {
if (pnmud->hdr.code == UDN_DELTAPOS) {
iBorder = g_iBorder;
if (pnmud->iDelta < 0) {
iBorder++;
} else if (0 < pnmud->iDelta) {
iBorder--;
}
iBorder = max(iBorder, 0);
if (g_iBorder == iBorder) {
return;
}
g_iBorder = iBorder;
SetDlgItemInt(hDlg, IDC_EDIT_BORDER, g_iBorder, FALSE);
InitPanel();
}
}
}
//==============================================================================
// パネル関連
//------------------------------------------------------------------------------
// ウィンドウクラスの登録
int MyRegisterClass(void)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof wcex;
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = g_hInstance;
wcex.hIcon = NULL;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = g_atcClassName;
wcex.hIconSm = NULL;
if (RegisterClassEx(&wcex) == 0) {
return -1;
}
return 0;
}
//------------------------------------------------------------------------------
// パネルの作成
int CreatePanel(HWND hWndParent)
{
// ウィンドウの作成
g_hPanel = CreateWindowEx(
WS_EX_TOOLWINDOW | WS_EX_TOPMOST | WS_EX_LAYERED, // ExStyle
g_atcClassName, // ClassName
_T("Panel"), // WindowName
WS_POPUP | WS_VISIBLE, // Style
g_iPanelX, // x
g_iPanelY, // y
1, // Width
1, // Height
NULL, // WndParent
NULL, // Menu
g_hInstance,
NULL);
if (g_hPanel == NULL) {
return -1;
}
SetLayeredWindowAttributes(g_hPanel, RGB(0x00,0x00,0x00), 0xBF,
LWA_COLORKEY | LWA_ALPHA);
InitPanel();
return 0;
}
//------------------------------------------------------------------------------
// パネルの初期化
void InitPanel(void)
{
HDC hdc;
HGDIOBJ hFontOld;
SIZE sz;
if (g_hPanel == NULL) {
return;
}
// フォントの作成
DeleteObject(g_hFont);
g_hFont = CreateFontIndirect(&g_lf);
// ウィンドウサイズの変更
hdc = GetDC(g_hPanel);
hFontOld = SelectObject(hdc, g_hFont);
GetTextExtentPoint32(hdc, _T("88:88:88"), 8, &sz);
SelectObject(hdc, hFontOld);
ReleaseDC(g_hPanel, hdc);
SetWindowPos(g_hPanel, HWND_TOP, 0, 0,
sz.cx + g_iBorder * 2, sz.cy + g_iBorder * 2, SWP_NOMOVE);
}
//------------------------------------------------------------------------------
// パネルの破壊
void DestroyPanel(void)
{
if (g_hPanel == NULL) {
return;
}
PostMessage(g_hPanel, WM_CLOSE, 0, 0);
}
//------------------------------------------------------------------------------
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg) {
case WM_TIMER:
InvalidateRect(hWnd, NULL, TRUE);
break;
case WM_PAINT:
OnPaint(hWnd);
break;
case WM_LBUTTONDOWN:
PostMessage(hWnd, WM_NCLBUTTONDOWN, HTCAPTION, lParam);
break;
case WM_CREATE:
g_uiIDEvent = SetTimer(hWnd, 1, 1000, NULL);
break;
case WM_DESTROY:
OnDestroyWnd(hWnd);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//------------------------------------------------------------------------------
void OnDestroyWnd(HWND hWnd)
{
RECT rcScreen;
if (g_uiIDEvent) {
KillTimer(hWnd, g_uiIDEvent);
g_uiIDEvent = 0;
}
if (GetWindowRect(hWnd, &rcScreen)) {
g_iPanelX = rcScreen.left;
g_iPanelY = rcScreen.top;
}
g_hPanel = NULL;
}
//------------------------------------------------------------------------------
void OnPaint(HWND hWnd)
{
HDC hdc;
PAINTSTRUCT ps;
HPEN hPen;
HGDIOBJ hFontOld;
HGDIOBJ hPenOld;
time_t timer;
struct tm tm;
TCHAR atcString[16];
int iStrLen;
hdc = BeginPaint(hWnd, &ps);
SetBkMode(hdc, TRANSPARENT);
hFontOld = SelectObject(hdc, g_hFont);
time(&timer);
localtime_s(&tm, &timer);
iStrLen = _stprintf_s(atcString, _T("%02d:%02d:%02d"),
tm.tm_hour, tm.tm_min, tm.tm_sec);
if (g_iBorder) {
BeginPath(hdc);
TextOut(hdc, g_iBorder, g_iBorder, atcString, iStrLen);
EndPath(hdc);
hPen = CreatePen(PS_SOLID, g_iBorder * 2, g_crBorder);
hPenOld = SelectObject(hdc, hPen);
StrokePath(hdc);
SelectObject(hdc, hPenOld);
DeleteObject(hPen);
}
SetTextColor(hdc, g_crText);
TextOut(hdc, g_iBorder, g_iBorder, atcString, iStrLen);
SelectObject(hdc, hFontOld);
EndPaint(hWnd, &ps);
}
// リソーススクリプト
#include <windows.h>
#include <commctrl.h>
#include "resource.h"
IDD_MAIN_DIALOG DIALOGEX 0, 0, 176, 64
STYLE WS_POPUPWINDOW | WS_MINIMIZEBOX
EXSTYLE WS_EX_APPWINDOW
CAPTION "Layered Window"
FONT 9, "MS Pゴシック"
BEGIN
PUSHBUTTON "パネル(&P)",IDC_BUTTON_PANEL,8,8,48,20
PUSHBUTTON "フォント(&F)",IDC_BUTTON_FONT,64,8,48,20
PUSHBUTTON "文字色(&T)",IDC_BUTTON_TEXT,120,8,48,20
LTEXT "縁取り幅(&S):",IDC_STATIC,8,36,48,12,SS_RIGHT
EDITTEXT IDC_EDIT_BORDER,64,36,40,16
CONTROL "",IDC_SPIN_BORDER,UPDOWN_CLASS,UDS_ARROWKEYS,104,36,8,16
PUSHBUTTON "縁取り色(&B)",IDC_BUTTON_BORDER,120,36,48,20
END