ホーム > カテゴリ > C/C++ >

オーナードローボタンを作成する(C/C++版)

オーナードローボタンを作成するサンプルです。

サンプルの実行画面

ソースコード

[Sample16.c]

//--------------------------------------------------------------------------------------
//  ■オーナードローボタンを作成する■ Sample NO.16
//
//--------------------------------------------------------------------------------------

//リンクの設定
//comctl32.libをリンクに追加

#include <windows.h>
#include <commctrl.h>

//コマンドID
#define ID_BUTTON1 1500
#define ID_BUTTON2 1501
#define ID_BUTTON3 1502

//コールバックプロシージャ
LRESULT CALLBACK  WindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);

HIMAGELIST hImageList;   //イメージリストのハンドル
HFONT      hFont;        //フォントのハンドル

//------------------------------------------------------
//■関数 ScreenCenterX(ローカル)
//■用途 ウインドウを中央にする為にX座標(LEFT)を算出する
//■引数
//        Width     ...ウインドウの横幅
//------------------------------------------------------
int ScreenCenterX(int Width)
{ 
 int X;
  X = (GetSystemMetrics(SM_CXSCREEN)- Width) / 2;
 if (X<0) X=0;
 return(X);
}

//------------------------------------------------------
//■関数 ScreenCenterY(ローカル)
//■用途 ウインドウを中央にする為にY座標(TOP)を算出する
//■引数
//        Height     ...ウインドウの縦幅
//------------------------------------------------------
int ScreenCenterY(int Height)
{ 
 int Y;
 Y= (GetSystemMetrics(SM_CYSCREEN)- Height) / 2;
 if (Y<0) Y=0;
 return(Y);
}

//------------------------------------------------------
//■関数 CreateMainWindow(ローカル)
//■用途 メインウインドウを作成する
//■引数
//        Width      ...ウインドウの横幅
//        Height     ...ウインドウの縦幅
//        Caption    ...タイトル名
//        hInstance  ...インスタンスハンドル
//        nCmdShow   ...ウインドウの表示形態
//        lpfnWndProc...コールバックプロシージャ
//        dwstyle    ...ウインドウスタイル
//        dwExstyle  ...拡張ウインドウスタイル
//        MenuID     ...メニューのID
//        hIcon      ...アイコン
//■戻り値
//  ウインドウのハンドル
//------------------------------------------------------
HWND CreateMainWindow(int Width,int Height,LPCTSTR Caption,HINSTANCE hInstance,int nCmdShow,WNDPROC lpfnWndProc, DWORD dwstyle,DWORD dwExstyle,LPCTSTR MenuID,HICON hIcon)
{
    HWND     hWnd;     //メインウインドウのハンドル
    WNDCLASS myClass;  //WNDCLASS構造体
    
   //WNDCLASS構造体を0で初期化
    ZeroMemory(&myClass,sizeof(WNDCLASS));
 
//--->WNDCLASS構造体の設定&ウインドウクラスの登録

    //ウインドウスタイルを設定 
    myClass.style         =CS_HREDRAW | CS_VREDRAW; 
    //コールバックプロシージャへのポインタ
    myClass.lpfnWndProc   = lpfnWndProc;    
    //インスタンスハンドルを設定
    myClass.hInstance        =hInstance;
    //カーソルの設定(Windows標準リソースを使用)  
    myClass.hCursor        =LoadCursor(NULL, IDC_ARROW);
    //ウインドウの背景を設定(デフォルトカラー)    
    myClass.hbrBackground    =(HBRUSH)COLOR_WINDOW;
    //クラス名の設定(Borland Delphi風)  
    myClass.lpszClassName    ="TForm";
    //アイコンの指定
    myClass.hIcon =hIcon;
    //メニューの設定
    myClass.lpszMenuName=MenuID;
        
    //ウィンドウ クラスを登録
    RegisterClass(&myClass); 
    
//--->ウインドウの作成&表示
   
    //メインウインドウの生成
    hWnd = CreateWindowEx(
                        //拡張ウインドウスタイル
                        dwExstyle,
                        //登録されたクラス名のアドレス 
                        "TForm",
                        //ウインドウ名
                        Caption,    
                        //ウインドウスタイルを設定
                        dwstyle,      
                        //X座標の位置設定
                        ScreenCenterX(Width),
                        //Y座標の位置設定
                        ScreenCenterY(Height),       
                        //横幅を設定
                        Width,       
                        //縦幅を設定
                        Height,  
                        //親ウインドウを設定
                        NULL,
                        //メニューを設定
                        NULL,        
                        //インスタンスを識別
                        hInstance,     
                        //作成したウインドウに渡すデータへのポインタ
                        NULL); 
     
    //ウインドウの表示(表示方法はnCmdShowに従う)
    ShowWindow(hWnd, nCmdShow);
    return(hWnd);
}

//------------------------------------------------------
//■関数名  ControlCreate
//■用途    ウインドウ(コントロール)を作成
//■引数
//       hwndParent ...親ウインドウのハンドル
//       Left       ...作成するウインドウの左隅のX座標
//       Top        ...作成するウインドウの左隅のY座標
//       Width      ...作成するウインドウの横幅
//       Height     ...作成するウインドウの縦幅
//       dwExStyle  ...ウインドウの拡張フラグ
//       dwFlag     ...ウインドウの作成フラグ
//       Caption    ...作成するウインドウのキャプション
//       ClassName  ...作成するウインドウクラス名
//       ChildID    ...子ウインドウの識別子
//       hInstance  ...インスタンスハンドル 
//■戻り値
//  子ウインドウのハンドル
//------------------------------------------------------
 HWND CreateControlWindow(HWND hwndParent, int Left, int Top,int Width, int Height,int dwExStyle ,int dwFlag ,LPCTSTR Caption, LPCTSTR ClassName,HMENU ChildID,HINSTANCE hInstance)
 { 
 return CreateWindowEx(dwExStyle,ClassName,Caption,WS_CHILD | WS_VISIBLE | dwFlag    ,
                         Left, Top, Width, Height, hwndParent, ChildID, hInstance, NULL);
 }

//---------------------------------------------------------------
//■関数 SetWindowFont
//■用途 ウインドウのフォントを変更する
//■引数
//        hwnd       ...フォントを変更するウインドウのハンドル
//        Height     ...フォントの縦幅
//        Weight     ...フォントの太さ 
//        Italic     ...斜体フラグ
//        Underlin   ...アンダーラインフラグ
//        StrikeOut  ...打ち消し線フラグ
//        FontName   ...フォントの名前
//---------------------------------------------------------------
HFONT SetWindowFont(HWND hwnd,int Height,int Weight,BOOL Italic,BOOL Underlin,BOOL StrikeOut, LPCTSTR FontName)
{
 HFONT hFont;
  hFont=  (CreateFont(-12,0,0,0,Weight,Italic,Underlin,StrikeOut,SHIFTJIS_CHARSET,
                    OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH,FontName));
  SendMessage(hwnd,WM_SETFONT,(WPARAM)hFont,TRUE); 
  return(hFont);
}

//--------------------------------------------------------
//■関数 WinMain
//■用途 メインの関数 
//■引数
// hInstance    ...現在のインスタンスのハンドル
// hPrevInstance...以前のインスタンスのハンドル
// pszCmdLine   ...コマンド ラインのアドレス
// nCmdShow     ...ウィンドウの表示状態
//--------------------------------------------------------
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
{    
   MSG    msg;

   CreateMainWindow(280,230,"オーナードローボタンを作成する",hInstance,nCmdShow,(WNDPROC)WindowProc,
       WS_OVERLAPPEDWINDOW,WS_EX_CONTROLPARENT | WS_EX_WINDOWEDGE,NULL,LoadIcon(NULL,MAKEINTRESOURCE(IDI_APPLICATION)));
  
  //送られてくるメッセージを翻訳してプロシージャに渡す  
  while (GetMessage(&msg, NULL, 0, 0)) 
   {
      TranslateMessage(&msg); 
      DispatchMessage(&msg);   
  } 
 return (msg.wParam);
}

//------------------------------------------------------
// ■関数 WindowProc
// ■用途 メインウインドウに送られるメッセージを処理
// ■引数
//        hwnd    ...ウインドウのハンドル
//        uMsg    ...メッセージID
//        wParam  ...第1メッセージ パラメータ    
//        lParam  ...第2メッセージ パラメータ
//------------------------------------------------------
LRESULT CALLBACK  WindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
    LPDRAWITEMSTRUCT _DrawItem=(LPDRAWITEMSTRUCT)lParam;
    LPCTSTR _buffer;
    int      ImgIndex=0;
    HBRUSH   hBrush;
    HBITMAP  hBMP;
    HWND     hButton[3];  
    HFONT    hFont;
    int i;
    
    switch (uMsg)
    {
      case WM_CREATE:
                              
                 //コントロール作成 
                 hButton[0]=  CreateControlWindow(hwnd,10,10,250,25,0,
                             BS_OWNERDRAW,"","BUTTON",(HMENU)ID_BUTTON1,(HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE));   
                 hButton[1]=  CreateControlWindow(hwnd,10,36,250,25,0,
                             BS_OWNERDRAW,"","BUTTON",(HMENU)ID_BUTTON2,(HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE));    
                 hButton[2]=  CreateControlWindow(hwnd,10,62,250,25,0,
                             BS_OWNERDRAW,"","BUTTON",(HMENU)ID_BUTTON3,(HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE));    
                 
                 //フォントの変更
                  hFont=SetWindowFont(hButton[0],-12,FW_REGULAR,FALSE,FALSE,FALSE,"MS Pゴシック");
                 SendMessage(hButton[1],WM_SETFONT,(WPARAM)hFont,TRUE); 
                 SendMessage(hButton[2],WM_SETFONT,(WPARAM)hFont,TRUE); 

                 //イメージリストを作成
                 InitCommonControls();
                 hImageList = ImageList_Create(16, 16, ILC_COLOR | ILC_MASK, 2, 0);
                 //イメージリストにビットマップを追加(100はリソースの番号を参照してください。)
                 for (i=1;i<4;i++)
                 {
                    hBMP = LoadBitmap((HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),(LPCTSTR)100+i);
                    ImageList_AddMasked(hImageList, hBMP, RGB(0,255,255));
                    DeleteObject(hBMP);   
                 }
                 break;
      case WM_DRAWITEM:
                 //ボタンだったら
                 if  (((UINT) wParam==ID_BUTTON1) || ((UINT) wParam==ID_BUTTON2) || ((UINT) wParam==ID_BUTTON3))
                 {
                     //選択状態かチェック   ※本当はフォーカスがあるときなども描画したほうが良い
                     if ((_DrawItem->itemState) & (ODS_SELECTED)) 
                     {
                       //ブラシ作成
                       hBrush=CreateSolidBrush(RGB(192,192,192));
                       //テキストのカラーを設定    
                       SetTextColor(_DrawItem->hDC,RGB(0,0,0));
                       //テキストの背景色を指定
                       SetBkColor(_DrawItem->hDC,RGB(192,192,192)) ;
                       //バックグラウンドを塗りつぶす
                       FillRect(_DrawItem->hDC,&_DrawItem->rcItem,hBrush);                   
                       //ブラシ削除
                       DeleteObject(hBrush);
                       //矩形範囲を盛り下げる
                       DrawEdge(_DrawItem->hDC,(LPRECT)&_DrawItem->rcItem,EDGE_SUNKEN,BF_RECT);
                     }
                    else  
                    {
                       //ブラシ作成
                       hBrush=CreateSolidBrush(RGB(192,192,192));
                       //テキストのカラーを設定
                       SetTextColor(_DrawItem->hDC,RGB(0,0,0));
                       //テキストの背景色を指定
                       SetBkColor(_DrawItem->hDC,RGB(192,192,192)) ;
                       //バックグラウンドを塗りつぶす
                       FillRect(_DrawItem->hDC,&_DrawItem->rcItem,hBrush);                   
                       //ブラシ削除
                       DeleteObject(hBrush);
                       //矩形範囲を盛り上げる
                       DrawEdge(_DrawItem->hDC,(LPRECT)&_DrawItem->rcItem,EDGE_RAISED,BF_RECT);
                    }
                      //コマンドID別の情報設定
                      switch  ((UINT) wParam)
                      {
                          case ID_BUTTON1: _buffer="新規作成",       ImgIndex=0;break;
                          case ID_BUTTON2: _buffer="ファイルを開く", ImgIndex=1;break;
                          case ID_BUTTON3: _buffer="上書き保存",     ImgIndex=2;break;
                      } 

                       //テキストを描画       
                       TextOut(_DrawItem->hDC,_DrawItem->rcItem.left+22,_DrawItem->rcItem.top+5, _buffer,strlen(_buffer));
                         //ビットマップを描画(アイテムのインデックスが超えた場合はなにもされない)    
                       ImageList_Draw(hImageList,ImgIndex,_DrawItem->hDC, 3, _DrawItem->rcItem.top+3, ILD_TRANSPARENT);
            
                 }
                 break;
      case WM_COMMAND:
                       if (LOWORD(wParam)==ID_BUTTON1) MessageBox(hwnd,"ボタン1がクリックされました。","情報",MB_ICONINFORMATION);
                       if (LOWORD(wParam)==ID_BUTTON2) MessageBox(hwnd,"ボタン2がクリックされました。","情報",MB_ICONINFORMATION);
                       if (LOWORD(wParam)==ID_BUTTON3) MessageBox(hwnd,"ボタン3がクリックされました。","情報",MB_ICONINFORMATION);
                       break;
      case WM_DESTROY: 
                       //イメージリストを破棄
                       ImageList_Destroy(hImageList); 
                       DeleteObject(hFont);
                       PostQuitMessage(0);  break;
      //その他のメッセージはWindowsに任せる
      default:return(DefWindowProc(hwnd, uMsg, wParam, lParam)); 
    }
    return (0);
}

ソースコード一式のダウンロード

capi_sample16.zip 4,334 バイト

動作環境

このサンプルは 「Windows98」及び「Microsoft Visual C++5.0」「Borland C++ Compiler 5.5」で確認しております。環境が異なる場合は正常に動作しない場合もございますのでご了承下さい。

Visual C++5.0でのコンパイル

VC5.0でサンプルをコンパイルする場合は新規プロジェクト(Win32Application)を作成後、各ファイルを追加してビルドしてください。

Borland C++ Compiler 5.5でのコンパイル

BCC5.5でサンプルをコンパイルする場合は「bcc32.exe」で*.c又は*.cppファイルをコンパイルします。リソースがある場合は「brc32.exe」で*resファイルを付与してください。

サンプルについて

このWindows APIサンプル集(C/C++版)は2000年頃にC/C++言語の学習の為に作成したものです。コードはエレガントではなく「初心者レベルのコーディング」です。仕事などの業務で利用する際にはエラー処理やメモリ解放などの再確認を必ずして下さい。





関連記事



公開日:2015年03月19日
記事NO:00472