開発環境 Microsoft Visual C++ 2010 Express (SP1)
実行環境 Microsoft Windows XP Home Edition (SP3)
プロジェクトの種類 Win32 プロジェクト
プロジェクト名 LayeredWnd
アプリケーションの種類 Windows アプリケーション
追加のオプション 空のプロジェクト
文字セット Unicode

LayeredWnd.cpp
#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);
}
 

resource.h
#define IDD_MAIN_DIALOG		100
 
#define IDC_STATIC		-1
#define IDC_BUTTON_PANEL	1000
#define IDC_BUTTON_FONT		1001
#define IDC_BUTTON_TEXT		1002
#define IDC_EDIT_BORDER		1003
#define IDC_SPIN_BORDER		1004
#define IDC_BUTTON_BORDER	1005
 

LayeredWnd.rc
// リソーススクリプト
 
#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
 
最終更新:2012年09月01日 16:46