プログレスバーの中に文字を表示したい!
のでAPIを調べてみる…。
だがAPIでは、サポートされていないようだ…。
で、投げていた…。
所が、何か降って来て閃いた!
だったらプロシージャを乗っ取れば良いんじゃない?
それならフックかな?
てな訳で調べれてみた…。
そしたらサブクラス化にすれば良いじゃん!
って事が分かった…。
あ!サブクラス化を完全に忘れてた…。
ここまで来たら直ぐ出来るよ!
※ソースは『Microsoft Visual C++ 6.0』だよ。
//--------------------------------------
#pragma comment( lib, "comctl32.lib" )
//--------------------------------------
#include <Windows.h>
#include <CommCtrl.h>
//--------------------------------------
WNDPROC OriginalProc;
//--------------------------------------
LRESULT CALLBACK ProgressBarProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
LRESULT Result = CallWindowProc( OriginalProc, hWnd, uMsg, wParam, lParam );
if( uMsg == WM_PAINT )
{
LPSTR String = "push A button!";
HDC DC = GetDC( hWnd );
SetTextColor( DC, 0x00FFFFFF );
SetBkMode( DC, TRANSPARENT );
TextOut( DC, 0, 0, String, strlen( String ) );
ReleaseDC( hWnd, DC );
}
return Result;
}
//--------------------------------------
LRESULT CALLBACK WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
static HWND hProgress;
switch( uMsg )
{
case WM_CREATE:
InitCommonControls( );
hProgress = CreateWindowEx( 0, PROGRESS_CLASS, "", WS_CHILD | WS_VISIBLE | PBS_SMOOTH, 40, 20, 200, 24, hWnd, 0, NULL, NULL );
OriginalProc = ( WNDPROC )SetWindowLong( hProgress, GWL_WNDPROC, ( LONG )ProgressBarProc );
break;
case WM_KEYUP:
if( wParam == VK_ESCAPE )
{
DestroyWindow( hWnd );
} else
if( wParam == 'A' )
{
SendMessage( hProgress, PBM_SETRANGE, 0, MAKELPARAM( 0, 100 ) );
for( int i = 0 ; i <= 100 ; i++ )
{
SendMessage( hProgress, PBM_SETPOS, i, 0 );
Sleep( 10 );
}
}
break;
case WM_DESTROY:
SetWindowLong( hProgress, GWL_WNDPROC, ( LONG )OriginalProc );
PostQuitMessage( 0 );
break;
default:
return DefWindowProc( hWnd, uMsg, wParam, lParam );
}
return 0;
}
//--------------------------------------
int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE, LPTSTR, int nCmdShow )
{
LPSTR name = "sample";
MSG msg;
HWND hWnd;
WNDCLASS wc;
memset( &wc, 0, sizeof( wc ) );
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.hbrBackground = ( HBRUSH )( COLOR_3DFACE + 1 );
wc.lpszMenuName =
wc.lpszClassName = name;
RegisterClass( &wc );
hWnd = CreateWindow( name, name, WS_OVERLAPPEDWINDOW
, 100, 100, 290, 80, NULL, NULL, hInstance, NULL );
ShowWindow( hWnd, nCmdShow );
UpdateWindow( hWnd );
while( GetMessage( &msg, NULL, 0, 0 ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
return( msg.wParam );
}
取り敢えず目的の第一弾は、達成した!
バーの重なる部分の文字の色変えやセンター合わせなど細工は第二段だね。
ここまで来たら後少し。
もうチョイ上等な処理は、こんな感じか?
//--------------------------------------
#pragma comment( lib, "comctl32.lib" )
//--------------------------------------
#include <Windows.h>
#include <CommCtrl.h>
//--------------------------------------
WNDPROC OriginalProc;
char ProgressBarText[30] = "push A or B button!";
//--------------------------------------
#if 0
// テキストだけ後付けの処理(比較用に用意)
LRESULT CALLBACK ProgressBarProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
LRESULT Result = CallWindowProc( OriginalProc, hWnd, uMsg, wParam, lParam );
if( uMsg == WM_PAINT )
{
int Length, X, Y, P, R;
SIZE Size;
RECT Rect, RectIn, RectOut;
HRGN RgnIn, RgnOut;
HDC hDC = GetDC( hWnd );
GetClientRect( hWnd, &Rect );
// ※補正
SetRect( &Rect, Rect.left + 1, Rect.top + 1, Rect.right - 2, Rect.bottom - 1 );
Length = strlen( ProgressBarText );
SetBkMode( hDC, TRANSPARENT );
GetTextExtentPoint32( hDC, ProgressBarText, Length, &Size );
X = ( Rect.right - Size.cx ) / 2;
Y = ( Rect.bottom - Size.cy ) / 2;
P = SendMessage( hWnd, PBM_GETPOS, 0, 0 );
R = SendMessage( hWnd, PBM_GETRANGE, FALSE, 0 );
P = Rect.left + ( Rect.right - Rect.left ) * P / R;
CopyRect( &RectIn, &Rect );
CopyRect( &RectOut, &Rect );
RectIn.right = RectOut.left = P;
RgnIn = CreateRectRgnIndirect( &RectIn );
RgnOut = CreateRectRgnIndirect( &RectOut );
SetTextColor( hDC, 0x00FFFFFF );
SelectClipRgn( hDC, RgnIn );
TextOut( hDC, X, Y, ProgressBarText, Length );
SetTextColor( hDC, 0x00000000 );
SelectClipRgn( hDC, RgnOut );
TextOut( hDC, X, Y, ProgressBarText, Length );
ReleaseDC( hWnd, hDC );
}
return Result;
}
#else
// ペイントを乗っ取って表示する処理
LRESULT CALLBACK ProgressBarProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
if( uMsg == WM_PAINT )
{
int Length, X, Y, P, R;
SIZE Size;
RECT Rect, RectIn, RectOut;
HRGN RgnIn, RgnOut;
PAINTSTRUCT PaintStruct;
HDC hDC;
hDC = BeginPaint( hWnd, &PaintStruct );
GetClientRect( hWnd, &Rect );
// ※補正
SetRect( &Rect, Rect.left + 1, Rect.top + 1, Rect.right - 2, Rect.bottom - 1 );
Length = strlen( ProgressBarText );
SetBkMode( hDC, TRANSPARENT );
GetTextExtentPoint32( hDC, ProgressBarText, Length, &Size );
X = ( Rect.right - Size.cx ) / 2;
Y = ( Rect.bottom - Size.cy ) / 2;
P = SendMessage( hWnd, PBM_GETPOS, 0, 0 );
R = SendMessage( hWnd, PBM_GETRANGE, FALSE, 0 );
P = Rect.left + ( Rect.right - Rect.left ) * P / R;
CopyRect( &RectIn, &Rect );
CopyRect( &RectOut, &Rect );
RectIn.right = RectOut.left = P;
RgnIn = CreateRectRgnIndirect( &RectIn );
RgnOut = CreateRectRgnIndirect( &RectOut );
SetTextColor( hDC, 0x00FFFFFF );
SelectClipRgn( hDC, RgnIn );
FillRect( hDC, &RectIn, ( HBRUSH )COLOR_HIGHLIGHTTEXT );
TextOut( hDC, X, Y, ProgressBarText, Length );
SetTextColor( hDC, 0x00000000 );
SelectClipRgn( hDC, RgnOut );
TextOut( hDC, X, Y, ProgressBarText, Length );
EndPaint( hWnd, &PaintStruct );
return 0;
}
return CallWindowProc( OriginalProc, hWnd, uMsg, wParam, lParam );
}
#endif
//--------------------------------------
LRESULT CALLBACK WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
static HWND hProgress;
switch( uMsg )
{
case WM_CREATE:
InitCommonControls( );
hProgress = CreateWindowEx( 0, PROGRESS_CLASS, "", WS_CHILD | WS_VISIBLE | PBS_SMOOTH, 40, 20, 200, 24, hWnd, 0, NULL, NULL );
OriginalProc = ( WNDPROC )SetWindowLong( hProgress, GWL_WNDPROC, ( LONG )ProgressBarProc );
break;
case WM_KEYUP:
if( wParam == VK_ESCAPE )
{
DestroyWindow( hWnd );
} else
if( wParam == 'A' )
{
strcpy( ProgressBarText, "*********************" );
InvalidateRect( hProgress, NULL, TRUE );
SendMessage( hProgress, PBM_SETRANGE, 0, MAKELPARAM( 0, 100 ) );
for( int i = 0 ; i <= 100 ; i++ )
{
SendMessage( hProgress, PBM_SETPOS, i, 0 );
Sleep( 10 );
}
} else
if( wParam == 'S' )
{
SendMessage( hProgress, PBM_SETRANGE, 0, MAKELPARAM( 0, 100 ) );
for( int i = 0 ; i <= 100 ; i++ )
{
wsprintf( ProgressBarText, "** %3d", i );
InvalidateRect( hProgress, NULL, TRUE );
SendMessage( hProgress, PBM_SETPOS, i, 0 );
Sleep( 10 );
}
}
break;
case WM_DESTROY:
SetWindowLong( hProgress, GWL_WNDPROC, ( LONG )OriginalProc );
PostQuitMessage( 0 );
break;
default:
return DefWindowProc( hWnd, uMsg, wParam, lParam );
}
return 0;
}
//--------------------------------------
int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE, LPTSTR, int nCmdShow )
{
LPSTR name = "sample";
MSG msg;
HWND hWnd;
WNDCLASS wc;
memset( &wc, 0, sizeof( wc ) );
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.hbrBackground = ( HBRUSH )( COLOR_3DFACE + 1 );
wc.lpszMenuName =
wc.lpszClassName = name;
RegisterClass( &wc );
hWnd = CreateWindow( name, name, WS_OVERLAPPEDWINDOW
, 100, 100, 290, 80, NULL, NULL, hInstance, NULL );
ShowWindow( hWnd, nCmdShow );
UpdateWindow( hWnd );
while( GetMessage( &msg, NULL, 0, 0 ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
return( msg.wParam );
}
出来てしまえば、出来なかった自分が阿保に思えるから不思議…。(汗)
ここまで出来れば、後はクラス化してまとめれば直ぐだ♪
サブクラス化を思い出せば直ぐだったなぁ~。
でも、また忘れそうなので記録しておこう!
最近のコメント