35章 メニューとキーボードアクセラレーター(その7)

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=shift_jis"></meta>
<title>35章 メニューとキーボードアクセラレーター(その7)
</title>
</head>

<body bgcolor="WHITE">
<font size="5">35章 メニューとキーボードアクセラレーター(その7)
</font>
<hr>
<p>
 今回は、メニューとキーボードアクセラレーターの最後として、フローティングポップアップメニューについて説明します。 フローティングポップアップメニューというのは、Windows95からポピュラーになったマウス右クリックで出て来るメニューの事です。<br>
 今回も6章のサンプルをベースに説明しますので、6章を読んでいない方は6章を読むとよく理解出来ます。
<p align="CENTER">
<a href="chap35.lzh">ダウンロード</a>
<hr>
<p>
<b>
・フローティングポップアップメニュー用メニューの作成の方法
</b>
<p>
 フローティングポップアップメニューを作成する場合も、リソースを用いる方法と前章の様に動的に作成する方法があります。<br>
 今回は、コーディング量が減り視覚的にメニューが作成出来るリソースを用いる方法を採用しました。
<p>
 では、メニューを作成する重要な画面を提示します。赤丸で囲んである箇所に注意して下さい。<b><i><u>フローティングポップアップメニューは、サブメニューだけを表示する</u></i></b>ので、この様なダミーを用意しておくとメニューを作りやすいです。
<p align="CENTER">
<hr>
<p>
<b>
・フローティングポップアップメニューを表示する方法
</b>
<p>
<table border="1" bgcolor="#F0F0F0">
<caption align="BOTTOM">リスト35-1
<tr><td>
<pre>
/* C言語で始めるWindowsプログラミング */
/* 35章のサンプルプログラム */
/* Programmed by Y.Kondo */
/* 注:TABサイズは4で見てください */
/* このファイルでは、メインウインドウのウインド*/
/*ウプロシージャが定義されている */

#define STRICT
#include &lt;windows.h&gt;
#include &lt;stdio.h&gt;
#include "wndproc.h"
#include "resource.h"

/*===============================================================================*/

/* このファイル内でのみ用いられる関数のプロトタイプ宣言 */
static LRESULT Wm_CreateProc(HWND,LPCREATESTRUCT);
static LRESULT Wm_RButtonDownProc(HWND,DWORD,WORD,WORD);
static LRESULT Wm_CommandProc(HWND,WORD,WORD,HWND);
static LRESULT Wm_DestroyProc(void);
static LRESULT Wm_PaintProc(HWND);

/* メインウインドウのウインドウプロシージャ */
LRESULT CALLBACK WindowProc(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam)
{
  switch(message)
   {
       case    WM_CREATE:
           return  Wm_CreateProc(hwnd,(LPCREATESTRUCT)lparam);
       case    WM_RBUTTONDOWN:     /*  マウスの右ボタンが押された場合  */
           return  Wm_RButtonDownProc(hwnd,wparam,LOWORD(lparam),HIWORD(lparam));  
       case    WM_COMMAND:         /*  メニューに対する処理    */
           return  Wm_CommandProc(hwnd,HIWORD(wparam),LOWORD(wparam),(HWND)lparam);
       case    WM_PAINT:           /*  再描画処理              */
           return  Wm_PaintProc(hwnd);
       case    WM_DESTROY:         /*  ウインドウの破壊後処理  */
           return  Wm_DestroyProc();
   }
   return  DefWindowProc(hwnd,message,wparam,lparam);
}

/*===============================================================================*/

/* このファイル内でのみ用いられる型定義 */
typedef enum
{
  RECTANGLE,
   TRIANGLE
} TState;

/* 図形の状態 */
static TState StateFlag=RECTANGLE;

/* アプリケーションのインスタンスハンドル */
HINSTANCE hInst;

static LRESULT Wm_CreateProc(HWND hwnd,LPCREATESTRUCT cs)
{
  hInst=cs-&gt;hInstance; /*  このウインドウプロシージャは使い回ししないから出来る技  */
   return  0;
}
/* ここでフローティングポップアップメニューを表示する */
static LRESULT Wm_RButtonDownProc(HWND hwnd,DWORD fwKeys,WORD xPos,WORD yPos)
{
  HMENU   hMenu;
   HMENU   hSubMenu;
   POINT   p;
<b>
  hMenu=LoadMenu(hInst,MAKEINTRESOURCE(IDR_MENU1));
   hSubMenu=GetSubMenu(hMenu,0);</b>
   /*  ここで、排他的処理を行う    */
   if(StateFlag==RECTANGLE)
       EnableMenuItem(hSubMenu,ID_RECTANGLE,MF_BYCOMMAND|MF_GRAYED);
   else
       EnableMenuItem(hSubMenu,ID_TRIANGLE,MF_BYCOMMAND|MF_GRAYED);
<b>
  /*クライエント座標からスクリーン座標に変換する*/    
   p.x=xPos;
   p.y=yPos;
   ClientToScreen(hwnd,&p;);

  TrackPopupMenu(hSubMenu,TPM_LEFTALIGN|TPM_TOPALIGN|TPM_RIGHTBUTTON,
       p.x,p.y,0,hwnd,NULL);

  DestroyMenu(hMenu);
</b>
  return  0;
}
static LRESULT Wm_CommandProc(HWND hwnd,WORD wNotifyCode,WORD wID,HWND hwndCtl)
{
  switch(wID)
   {
       case    ID_RECTANGLE:
           StateFlag=RECTANGLE;
           InvalidateRect(hwnd,NULL,TRUE);
           UpdateWindow(hwnd);
           break;
       case    ID_TRIANGLE:
           StateFlag=TRIANGLE;
           InvalidateRect(hwnd,NULL,TRUE);
           UpdateWindow(hwnd);
           break;
   }
   return  0;
}
static LRESULT Wm_DestroyProc(void)
{
  PostQuitMessage(0);
   return  0;
}

static LRESULT Wm_PaintProc(HWND hwnd)
{
  PAINTSTRUCT ps;
   HDC         PaintDC;
   /*  四角形のデータ  */
   POINT   RA[]={{10,10},{190,10},{190,190},{10,190},{10,10}};
   /*  三角形のデータ  */
   POINT   TA[]={{100,10},{190,190},{10,190},{100,10}};

  if(GetUpdateRect(hwnd,NULL,TRUE))
   {
       PaintDC=BeginPaint(hwnd,&ps;);
       if(StateFlag==RECTANGLE)
           Polyline(PaintDC,RA,sizeof(RA)/sizeof(POINT));
       else
           Polyline(PaintDC,TA,sizeof(TA)/sizeof(POINT));
       EndPaint(hwnd,&ps;);
   }
   return  0;
}
</pre>
</table>
<p>
<b>
・フローティングポップアップメニュー表示の概略
</b>
<p>
 フローティングポップアップメニューの作成は、以下の手順で行います。<br>
・メニューを作成する(LoadMenu関数)<br>
・表示すべきサブメニューのハンドルを取得する(GetSubMenu関数)<br>
・クライアント座標からスクリーン座標に、座標変換をする(<b>ClientToScreen関数</b>)<br>
・フローティングポップアップメニューを表示する(<b>TrackPopupMenu関数</b>)<br>
・メニューを破棄する(DestroyMenu関数)<br>
<hr>
<p>
<b>
・重要な関数
</b>
<p>
<b>
・TrackPopupMenu関数
</b>
<p>
 フローティングポップアップメニューを表示する関数です。<br>
 第1引数は、表示するサブメニューのハンドル。第2引数は、フローティングポップアップメニューを表示する位置決めなどのフラグ。第3引数と第4引数はフローティングポップアップメニューを表示さす位置。この二つは、スクリーン座標系である事に注意して下さい。第5引数は予約。第6引数は、フローティングポップアップメニューに関連付けるウインドウのウインドウハンドル。第7引数は、フローティングポップアップメニューが消去されずにマウスのボタンをクリック出来る矩形を表わします。普通は、NULLです。
<p>
 第2引数について<br>
 TPM_CENTERALIGN、TPM_LEFTALIGN、そしてTPM_RIGHTALIGNは排他的に選択します。これは、指定したX座標に対するフローティングポップアップメニューの位置を決めます。<br>
 同様にY座標に関しては、TPM_BOTTOMALIGN、TPM_TOPALIGN、TPM_VCENTERALIGNがあります。これら3つも排他的です。<br>
 あと、メニュー項目を選択するのに使うボタンを決めるフラグもあります。TPM_LEFTBUTTONでは、マウスの左ボタンでのみメニュー項目を選択できます。これに対し、TPM_RIGHTBUTTONを選択すると、左右どちらのボタンでもメニュー項目を選択出来るようになります。この2つのフラグは排他的はありません。どうも、マウスの右ボタンだけの選択は出来ないようです。
<p>
 戻り値は、成功するとTRUEを返し、失敗するとFALSEを返します。
<p>
<b>
・ClientToScreen関数
</b>
<p>
 クライエント座標からスクリーン座標に変換する関数です。TrackPopupMenu関数の第3引数と第4引数がスクリーン座標を要求し、WM_RBUTTONDOWNメッセージに付随する情報が、マウスのクライエント座標ゆえ、この関数で変換する必要があるのです。<br>
 第1引数は、クライエント座標を持つウインドウのウインドウハンドル。第2引数は、POINT構造体変数へのポインタです。POINT構造体は以下のように定義されています。
<p>
<table border="1" bgcolor="#F0F0F0">
<tr><td>
<pre>
typedef struct tagPOINT {
  LONG x; 
   LONG y; 
} POINT;
</pre>
</table>
<p>
 変換後の値もここに格納されます。
<p>
 戻り値は、成功するとTRUEを返し、失敗するとFALSEを返します。
<hr>
<p>
 さてどうでしたでしょうか?7回に渡ってメニューとキーボードアクセラレーターについて解説しました。
<p>
 次回からは、グラフィックス・デバイス・インターフェース(GDI)の解説を行います。
<p>
 では、お楽しみに。
<p align="RIGHT">
2003年1月18日<br>
<hr>
<p align="RIGHT">
<a href="/web/20150528092522/http://web.kyoto-inet.or.jp:80/people/ysskondo/index.html">目次</a><br>
<hr>
<p align="RIGHT">
著作権者:近藤妥
</body>
</html>

  • 最終更新:2018-03-11 05:31:23

このWIKIを編集するにはパスワード入力が必要です

認証パスワード