コマンドボタンを作成しアイコンを描画 <TOP>
ピクチャボックスを利用して、コマンドボタン、アイコンおよびフォーカス用点線も描画してみます。
CreateFontIndirect
論理フォントを作成
SelectObject
指定されたデバイスコンテキストのオブジェクトを選択
GetSysColor
システムの背景色を取得
SetBkColor
デバイスコンテキストの背景色を設定
DrawFrameControl
指定されたタイプとスタイルを備える、ボタンやスクロールバーなどのフレームコントロールを描画
DrawText
文字列を指定領域に出力
ExtractIconEx
EXE・DLLから大きいアイコン・小さいアイコンを取得
DrawIconEx
アイコンを描画
DrawEdge
矩形に3D効果を与える
DrawFocusRect
フォーカスを得た時の点線の枠を描く
SetCapture
指定のウィンドウにマウスキャプチャを設定
ReleaseCapture
マウスのキャプチャを解放
DestroyIcon
アイコンのハンドルを解放
GetDC
デバイスコンテキストのハンドルを取得
ReleaseDC
デバイスコンテキストを解放
DeleteObject
システムリソースを解放
ピクチャボックスを利用してコマンドボタンを作成しアイコンを描画しています。
あらかじめ作成してある、16ドット・32ドットサイズのアイコン「favicon.ico」、16ドットサイズのBitmapを利用しています。
他のウィンドウが重なったとき、リサイズ時に再描画されないなど欠点があります。Timerで強制的に再描画していますが、ちょっと挙動が変ですね(^^;)
Visual Basic での Refresh と、F-Basic でのそれとは、動作が異なるようです。
RedrawWindow、UpdateWindowなどを試してみましたが、今のところ思い通りの動作はしてくれません。
'================================================================ '= コマンドボタンとアイコン描画 '= フォーカス用点線も描画 '= (DrawFrameControl5.bas) '================================================================ #include "Windows.bi" Type RECT Left As Long Top As Long Right As Long Bottom As Long End Type #define LF_FACESIZE 32 Type LOGFONT lfHeight As Long lfWidth As Long lfEscapement As Long lfOrientation As Long lfWeight As Long lfItalic As byte lfUnderline As byte lfStrikeOut As byte lfCharSet As byte lfOutPrecision As byte lfClipPrecision As byte lfQuality As byte lfPitchAndFamily As byte lfFaceName(LF_FACESIZE) As byte End Type ' 論理フォントを作成 Declare Function Api_CreateFontIndirect& Lib "gdi32" Alias "CreateFontIndirectA" (lpLogFont As LOGFONT) ' 指定されたデバイスコンテキストのオブジェクトを選択 Declare Function Api_SelectObject& Lib "gdi32" Alias "SelectObject" (ByVal hDC&, ByVal hObject&) ' システムの背景色を取得 Declare Function Api_GetSysColor& Lib "user32" Alias "GetSysColor" (ByVal nIndex&) ' デバイスコンテキストの背景色を設定 Declare Function Api_SetBkColor& Lib "gdi32" Alias "SetBkColor" (ByVal hDC&, ByVal crColor&) ' 指定されたタイプとスタイルを備える、ボタンやスクロールバーなどのフレームコントロールを描画 Declare Function Api_DrawFrameControl& Lib "user32" Alias "DrawFrameControl" (ByVal hDC&, lpRect As RECT, ByVal un1&, ByVal un2&) ' 文字列を指定領域に出力 Declare Function Api_DrawText& Lib "user32" Alias "DrawTextA" (ByVal hDC&, ByVal lpStr$, ByVal nCount&, lpRect As RECT, ByVal wFormat&) ' EXE・DLLから大きいアイコン・小さいアイコンを取得 Declare Function Api_ExtractIconEx& Lib "shell32" Alias "ExtractIconExA" (ByVal lpszFile$, ByVal nIconIndex&, phiconLarge&, phiconSmall&, ByVal nIcons&) ' アイコンを描画 Declare Function Api_DrawIconEx& Lib "user32" Alias "DrawIconEx" (ByVal hDC&, ByVal xLeft&, ByVal yTop&, ByVal hIcon&, ByVal cxWidth&, ByVal cyWidth&, ByVal istepIfAniCur&, ByVal hbrFlickerFreeDraw&, ByVal diFlags&) ' 矩形に3D効果を与える Declare Function Api_DrawEdge& Lib "user32" Alias "DrawEdge" (ByVal hDC&, qrc As RECT, ByVal edge&, ByVal grfFlags&) ' フォーカスを得た時の点線の枠を描く Declare Function Api_DrawFocusRect& Lib "user32" Alias "DrawFocusRect" (ByVal hDC&, lpRect As RECT) ' 指定のウィンドウにマウスキャプチャを設定 Declare Function Api_SetCapture& Lib "user32" Alias "SetCapture" (ByVal hWnd&) ' マウスのキャプチャを解放 Declare Function Api_ReleaseCapture& Lib "user32" Alias "ReleaseCapture" () ' アイコンのハンドルを解放 Declare Function Api_DestroyIcon& Lib "user32" Alias "DestroyIcon" (ByVal hIcon&) ' 指定されたウィンドウのクライアント領域または画面全体を表すディスプレイデバイスコンテキストのハンドルを取得 Declare Function Api_GetDC& Lib "user32" Alias "GetDC" (ByVal hWnd&) ' デバイスコンテキストを解放 Declare Function Api_ReleaseDC& Lib "user32" Alias "ReleaseDC" (ByVal hWnd&, ByVal hDC&) ' 論理オブジェクトを削除し、そのオブジェクトに関連付けられていたすべてのシステムリソースを解放 Declare Function Api_DeleteObject& Lib "gdi32" Alias "DeleteObject" (ByVal hObject&) #define DFC_BUTTON 4 'ボタンコントロールを描画 #define DFCS_BUTTONPUSH &H10 'プッシュボタン #define DFCS_PUSHED &H200 '押された状態 #define DT_RIGHT &H2 'テキストを右揃え #define DT_LEFT &H0 'テキストを左揃え #define DT_CENTER &H1 'テキストを水平方向に中央揃えで表示します。 #define DT_VCENTER &H4 'テキストを垂直方向の中央揃え。DT_SINGLELINEと同時に指定する必要がある #define DT_SINGLELINE &H20 'テキストを改行せず、一行で表示 #define COLOR_BTNFACE 15 'コマンドボタンの表面色 #define LR_LOADFROMFILE &H10 '外部ファイルからロードする #define DST_BITMAP &H4 'ビットマップ #define DI_NORMAL 3 'DI_IMAGEとDI_MASKの組み合わせ #define BF_RECT (&H1 Or &H2 Or &H4 Or &H8) '(BF_LEFT Or BF_TOP Or BF_RIGHT Or BF_BOTTOM) #define RDW_ALLCHILDREN &H80 '子ウィンドウがあるときは、それらも再描画の対象とする #define RDW_ERASE &H4 'ウィンドウの再描画時に、WM_ERASEBKGNDを送る。RDW_INVALIDATEフラグと同時に指定する必要がある #define RDW_ERASENOW &H200 '必要であれば、関数が制御を返す前に、影響を受けたウィンドウ(RDW_ALLCHILDRENまたはRDW_NOCHILDRENのフラ #define RDW_FRAME &H400 '更新領域と交差する非クライアント領域の部分にも、WM_NCPAINTを送る。RDW_INVALIDATEフラグと同時に指定す #define RDW_INTERNALPAINT &H2 'ウィンドウが無効な領域を持つか持たないかに関わらず、WM_PAINTメッセージをウィンドウにポストする #define RDW_INVALIDATE &H2 '指定したウィンドウ内の領域を無効化する #define RDW_NOCHILDREN &H40 '子ウィンドウがあるときは、それらを再描画の対象から外す #define RDW_NOERASE &H20 '未処理 WM_ERASEBKGNDを送らないようにする #define RDW_NOFRAME &H800 '未処理のWM_NCPAINTを送らないようにする。RDW_VALIDATEフラグと同時に指定する必要がる #define RDW_NOINTERNALPAINT &H10 '未処理の内部 WM_PAINTを送らないようにします。 #define RDW_UPDATENOW &H100 '必要であれば、関数が制御を返す前に、影響を受けたウィンドウ(RDW_ALLCHILDRENフラグまたはRDW_NOCHILDREN #define RDW_VALIDATE &H8 '指定したウィンドウ内の領域を有効化する Var Shared mPushed As Integer Var Shared mFocus As Integer Var Shared rc As RECT Var Shared Picture1 As Object Var Shared Button1 As Object Var Shared Timer1 As Object Picture1.Attach GetDlgItem("Picture1") Button1.Attach GetDlgItem("Button1") : Button1.SetFontSize 14 Timer1.Attach GetDlgItem("Timer1") '================================================================ '= コマンドボタンを描画 '================================================================ Declare Sub ButtonDraw edecl () Sub ButtonDraw() Var rc2 As RECT Var hDC As Long Var hIcon As Long Var lIcon As Long Var sIcon As Long Var State As Long Var Caption As String Var lf As LOGFONT Var rFont As Long Var Size As Integer Var BkCol As Long Var Edge As Long Var Ret As Long 'Picture1のデバイスコンテキストを取得 hDC = Api_GetDC(Picture1.GethWnd) 'ハンドルを取得 'Iconの場合(32x32、16x16の合成) hIcon = Api_ExtractIconEx("favicon.ico", 0, lIcon, sIcon, 1) 'Bmpの場合(16x16) ' hIcon = Api_ExtractIconEx("fbtip16.bmp", 0, lIcon, sIcon, 1) 'キャプションを設定 Caption = " F-Basic Tips" 'ボタンの色をシステムより取得 BkCol = Api_GetSysColor(COLOR_BTNFACE) 'バックカラーに指定 Ret = Api_SetBkColor(hDC, BkCol) 'フォントサイズ、日本語、イタリック指定 Size = 14 lf.lfHeight = Size lf.lfCharSet = 128 lf.lfItalic = 1 rFont = Api_CreateFontIndirect(lf) Ret = Api_SelectObject(hDC, rFont) 'ボタンの凹凸を設定 State = DFCS_BUTTONPUSH If mPushed = True Then State = State Or DFCS_PUSHED End If 'ボタンの矩形領域を指定 rc.Left = 0 : x = 0 rc.Top = 0 : y = 0 rc.Right = Picture1.GetWidth rc.Bottom = Picture1.GetHeight 'フォーカス用の矩形領域を指定 rc2.Left = rc.Left + 4 rc2.Top = rc.Top + 4 rc2.Right = rc.Right - 4 rc2.Bottom = rc.Bottom - 4 'ボタンを描画 Ret = Api_DrawFrameControl(hDC, rc, DFC_BUTTON, State) '押された場合、キャプションをずらす If mPushed = True Then rc.Left = 2 : x = 2 rc.Top = 2 : y = 2 End If 'ボタンの外形 Ret = Api_DrawEdge(hDC, rc, Edge, BF_RECT) 'キャプションを描画 Ret = Api_DrawText(hDC, Caption, Len(Caption), rc, DT_CENTER Or DT_VCENTER Or DT_SINGLELINE) 'Iconを描画 Ret = Api_DrawIconEx(hDC, x + 4, y + 4, sIcon, 0, 0, ByVal 0, 0, DI_NORMAL) 'フォーカス用の矩形を描く If mFocus = True Then Ret = Api_DrawFocusRect(hDC, rc2) End If 'デバイスコンテキスト、ハンドルの解放 Ret = Api_ReleaseDC(Picture1.GethWnd, hDC) Ret = Api_DestroyIcon(hIcon) Ret = Api_DeleteObject(rFont) End Sub '================================================================ '= '================================================================ Declare Sub MainForm_Start edecl () Sub MainForm_Start() Timer1.SetInterval 5 Timer1.Enable -1 End Sub '================================================================ '= マウスを動かしたとき '================================================================ Declare Sub Picture1_MouseMove edecl(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As Single, ByVal y As Single) Sub Picture1_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As Single, ByVal y As Single) Var Ret As Long 'マウスが Picture 上にあるとき If x >= 0 And y >= 0 And x <= Picture1.GetWidth And y <= Picture1.GetHeight Then Ret = Api_SetCapture(Picture1.GethWnd) ButtonDraw 'マウスが Picture1 を外れたとき Else Ret = Api_ReleaseCapture mPushed = False mFocus = False ButtonDraw End If End Sub '================================================================ '= マウスを押したとき '================================================================ Declare Sub Picture1_MouseDown edecl (Button As Integer, Shift As Integer, x As Single, y As Single) Sub Picture1_MouseDown(Button As Integer, Shift As Integer, x As Single, y As Single) Var Ret As Long Ret = Api_SetCapture(Picture1.GethWnd) mPushed = True mFocus = True ButtonDraw SetFocus End Sub '================================================================ '= マウスを離したとき '================================================================ Declare Sub Picture1_MouseUp edecl (Button As Integer, Shift As Integer, x As Single, y As Single) Sub Picture1_MouseUp(Button As Integer, Shift As Integer, x As Single, y As Single) Var Ret As Long Ret = Api_ReleaseCapture mPushed = False ButtonDraw End Sub '================================================================ '= '================================================================ Declare Sub Timer1_Timer edecl () Sub Timer1_Timer() ButtonDraw End Sub '================================================================ '= '================================================================ While 1 WaitEvent Wend Stop End