Top > プログラミング関連 > GLUTウィンドウにメニューをつける
2009/7/29 記述
お手軽な3DライブラリとしてよくGLUTが使われています。ライブラリがウィンドウ作成から描画までの大半の面倒を見てくれているおかげで非常に簡単に3D表示ができますが、反面、ライブラリ内部に隠れた部分が多すぎて少し凝ったことは何もできないという問題点があります。
少しダイアログやメニューを追加したいだけなのに、GLUTがいきなり使えなくなってしまうのではいきなりハードルが高くなります。もちろんGLUTでも複数ウィンドウやマウスクリックからのポップアップメニューが使えますが、それだけでは不十分です。
そこで、Windows限定ながら、GLUTで作ったウィンドウにメニューを追加してみました。今回はGLUT以外のライブラリを使わないということで、Win32 APIを使用します。Win32 APIを使用したWindowsプログラミングについては、Wisdom Soft等を参考にしてください。
無理矢理なので、場合によっては失敗するかもしれません。そのときはご容赦を。
要は、GLUTで作ったウィンドウを乗っ取り、自前の処理を本来の処理の前に追加してやるわけです。Windowsプログラミングにおいては、ウィンドウハンドルが分かれば、(一部制限はあるものの)大体のことができますから、ダイアログを表示することもメニューを追加することも可能になります。
ウィンドウの検索にはEnumWindows()を、ウィンドウプロシージャの差し替えにはGetWindowLong()/SetWindowLong()を用います。
//乗っ取り対象ウィンドウの検索
BOOL CALLBACK enumWindowsProc(HWND hWnd,LPARAM lParam)
{
HANDLE hModule=(HANDLE)GetWindowLong(hWnd,GWL_HINSTANCE);
if(GetModuleHandle(NULL)==hModule){
//自分のプロセスが作ったウィンドウを見つけた
//--ウィンドウクラス名比較
char szClassName[256];
GetClassName(hWnd,szClassName,sizeof(szClassName)/sizeof(szClassName[0]));
if(strncmp(szClassName,"GLUT",strlen(szClassName))==0){
g_hWnd=hWnd;
return FALSE; //break
}
}
return TRUE; //continue
}
//ウィンドウの乗っ取り
bool overrideGLWindow()
{
EnumWindows(enumWindowsProc,0);
if(g_hWnd){
originalWndProc=(WNDPROC)GetWindowLong(g_hWnd,GWL_WNDPROC);
SetWindowLong(g_hWnd,GWL_WNDPROC,(LONG)overrideWndProc);
return true;
}else{
return false;
}
}
//---
//乗っ取り後のプロシージャ
LRESULT CALLBACK overrideWndProc(HWND hWnd , UINT msg , WPARAM wParam , LPARAM lParam)
{
switch (msg) {
...(省略)...
default:
if(originalWndProc){
return CallWindowProc(originalWndProc,hWnd , msg , wParam , lParam);
}else{
return DefWindowProc(hWnd,msg,wParam,lParam);
}
}
}
このコードにはNYSL 0.9982を適用します。