MDIを表示する

 かなり回りくどいやり方ですが FreeGlut でも MDI を使う事はできます。

resource.h

#define IDM_NEW 101
#define IDM_EXIT 102
#define IDM_CLOSE 103
#define IDM_CASCADE 104
#define IDM_TILE 105
#define IDM_CLOSEALL 106
#define IDM_ARRANGE 107
#define ID_STATUS 108
#define IDM_INVISIBLE 109
#define IDM_VISIBLE 110

 

menu.rc

#include "resource.h"
 
OWNERMENU MENU DISCARDABLE
BEGIN
    POPUP "ファイル"
    BEGIN
        MENUITEM "新規作成",                IDM_NEW
        MENUITEM "終了",                    IDM_EXIT
    END
END

DOCUMENT MENU DISCARDABLE
BEGIN
    POPUP "ファイル"
    BEGIN
        MENUITEM "新規作成",                IDM_NEW
        MENUITEM "閉じる",                  IDM_CLOSE
        MENUITEM SEPARATOR
        MENUITEM "終了",                    IDM_EXIT
    END
    POPUP "ウィンドウ"
    BEGIN
  MENUITEM "クライアント領域を消す"  IDM_INVISIBLE
  MENUITEM "クライアント領域を表示"  IDM_VISIBLE
        MENUITEM "重ねて表示",              IDM_CASCADE
        MENUITEM "並べて表示",              IDM_TILE
        MENUITEM "すべて閉じる",            IDM_CLOSEALL
        MENUITEM "アイコンの整列",          IDM_ARRANGE
    END
END

main.cpp

#pragma comment(linker, "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")
#pragma comment(lib, "comctl32.lib")
#include <windows.h>
#include <GL/freeglut/freeglut.h>
#include "resource.h"
#include <commctrl.h> //CreateStatusWindow()のために必要


//FreeGlutのウインドウプロシージャを置き換える為の変数
WNDPROC WndProc=NULL; //元のウィンドウプロシージャ
HWND hWnd2=NULL; //ウィンドウハンドル
HMENU hMenu=NULL; //メニュー
HWND hStatusbar;     // ステータスバーのハンドル

HMENU hMenuFirst, hMenuDoc;
HMENU hMenuFirstWnd, hMenuDocWnd;
HINSTANCE hInst;
HWND hClient;

int doc_no;//ドキュメントの番号
wchar_t ChildDoc[] = L"document"; //ドキュメント
bool flag = false;

#define IDM_FIRSTCHILD 1000

#define WIDTH 640
#define HEIGHT 480

int width=0,height=0;
int pos_x=100,pos_y=100;

//回転用
float anglex = 0.0f;
//白
GLfloat white[] = { 1.0, 1.0, 1.0, 1.0 };

LRESULT CALLBACK DocProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp){
    static HWND hClient, hFrame;
    HWND hEdit;
    RECT rc;

    switch (msg) {
        case WM_CREATE:
            hClient = GetParent(hWnd);
            hFrame = GetParent(hClient);
            GetClientRect(hWnd, &rc);
            hEdit = CreateWindow(
                L"EDIT", NULL,
                WS_VISIBLE | WS_CHILD | ES_WANTRETURN | ES_MULTILINE |
                ES_AUTOVSCROLL | WS_VSCROLL |
                ES_AUTOHSCROLL | WS_HSCROLL,
                rc.left, rc.top,
                rc.right - rc.left,
                rc.bottom - rc.top,
                hWnd, NULL,
                hInst, NULL);
            return 0;
        case WM_SIZE:
            GetClientRect(hWnd, &rc);
            hEdit = GetWindow(hWnd, GW_CHILD);
            MoveWindow(hEdit, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE);
            break;
        case WM_MDIACTIVATE:
            if (lp == (LPARAM)hWnd)
                SendMessage(hClient, WM_MDISETMENU, (WPARAM)hMenuDoc, (LPARAM)hMenuDocWnd);
            if (lp != (LPARAM)hWnd)
                SendMessage(hClient, WM_MDISETMENU, (WPARAM)hMenuFirst, (LPARAM)hMenuFirstWnd);
            DrawMenuBar(hFrame);
            return 0;
    }
           
    return (DefMDIChildProc(hWnd, msg, wp, lp));
}
BOOL CALLBACK CloseAllProc(HWND hWnd, LPARAM lp){
    SendMessage(GetParent(hWnd), WM_MDIDESTROY, (WPARAM)hWnd, 0);
        return TRUE;
}
int MyRegisterWC(WNDPROC lpfnWndProc, LPCWSTR lpszClassName, HBRUSH hbrBack){
    WNDCLASSEX wc;

    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = lpfnWndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInst;        //インスタンス
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = hbrBack;
    wc.lpszMenuName = NULL;    //メニュー名
    wc.lpszClassName = lpszClassName;
    wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

    return(RegisterClassEx(&wc));
}

//置き換えた後のプロシージャ
LRESULT CALLBACK WndProc2(HWND hWnd , UINT msg , WPARAM wParam , LPARAM lParam){
 HWND hChild;
 CLIENTCREATESTRUCT ccs;
 MDICREATESTRUCT mdic;
    wchar_t str[64], *str_org = L"No.%d";
 RECT rc;
 switch( msg ){
 case WM_SIZE:
  width=LOWORD(lParam);
  height=HIWORD(lParam);
  GetWindowRect(hStatusbar,&rc);
  height=height-(rc.bottom-rc.top);
  if(!flag){
  ccs.hWindowMenu = hMenuFirstWnd;
        ccs.idFirstChild = IDM_FIRSTCHILD;
        hClient = CreateWindow(L"MDICLIENT", NULL, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN,
           0, 0, width, height, hWnd, (HMENU)1, hInst,(LPVOID)&ccs);
  flag=true;
   }
  SendMessage( hStatusbar, WM_SIZE, wParam, lParam );
  return DefFrameProc(hWnd,hClient,msg,wParam,lParam);
 case WM_COMMAND:
  switch (LOWORD(wParam)){
  case IDM_INVISIBLE:
   MoveWindow(hClient,0,0,0,0,1);
  return DefFrameProc(hWnd,hClient,msg,wParam,lParam);
  case IDM_VISIBLE:
   MoveWindow(hClient,0,0,width,height,1);
  return DefFrameProc(hWnd,hClient,msg,wParam,lParam);
  case IDM_NEW:
   doc_no++;
      wsprintf(str, str_org, doc_no);
      mdic.szClass = ChildDoc;
      mdic.szTitle = str;
      mdic.hOwner = hInst;
      mdic.x = CW_USEDEFAULT;
      mdic.y = CW_USEDEFAULT;
      mdic.cx = 240;
      mdic.cy = 120;
      mdic.style = 0;
      mdic.lParam = 0;
   MoveWindow(hClient,0,0,width,height,1);
      hChild = (HWND)SendMessage(hClient, WM_MDICREATE, 0,(LPARAM)&mdic);
      return DefFrameProc(hWnd,hClient,msg,wParam,lParam);
   case IDM_CLOSE:
      hChild = (HWND)SendMessage(hClient, WM_MDIGETACTIVE, 0, 0);
      if (hChild)SendMessage(hClient, WM_MDIDESTROY, (WPARAM)hChild, 0);
   return DefFrameProc(hWnd,hClient,msg,wParam,lParam);
   case IDM_EXIT:
      SendMessage(hWnd, WM_CLOSE, 0, 0);
      return DefFrameProc(hWnd,hClient,msg,wParam,lParam);
   case IDM_CLOSEALL:
      EnumChildWindows(hClient, &CloseAllProc, 0);
   doc_no=0;
      return DefFrameProc(hWnd,hClient,msg,wParam,lParam);
   case IDM_TILE:
    MoveWindow(hClient,0,0,width,height,1);
    SendMessage(hClient, WM_MDITILE, 0, 0);
      return DefFrameProc(hWnd,hClient,msg,wParam,lParam);
   case IDM_CASCADE:
    MoveWindow(hClient,0,0,width,height,1);
       SendMessage(hClient, WM_MDICASCADE, 0, 0);
       return DefFrameProc(hWnd,hClient,msg,wParam,lParam);
   case IDM_ARRANGE:
      SendMessage(hClient, WM_MDIICONARRANGE, 0, 0);
      return DefFrameProc(hWnd,hClient,msg,wParam,lParam);
   default:
      hChild = (HWND)SendMessage(hClient, WM_MDIGETACTIVE, 0, 0);
      if (IsWindow(hChild))SendMessage(hChild, WM_COMMAND, wParam, lParam);
      return DefFrameProc(hWnd,hClient,msg,wParam,lParam);
  }
 case WM_CLOSE:
  SendMessage(hWnd, WM_COMMAND, IDM_CLOSEALL, 0);
  if (GetWindow(hClient, GW_CHILD))return 0;
  PostQuitMessage(0);
  return 0;
 case WM_DESTROY:
  PostQuitMessage(0);
  return 0;
 default: 
  if(WndProc){
   return CallWindowProc(WndProc,hWnd , msg , wParam , lParam);
  }else{
   return DefFrameProc(hWnd,hClient,msg,wParam,lParam);
  }
 }
}

//ウィンドウの検索
BOOL CALLBACK enumWindowsProc(HWND hWnd,LPARAM lParam){
 HANDLE hModule=(HANDLE)GetWindowLong(hWnd,GWL_HINSTANCE);
 if(GetModuleHandle(NULL)==hModule){
  wchar_t ClassName[256];
  GetClassNameW(hWnd,ClassName,sizeof(ClassName)/sizeof(ClassName[0]));
  if(wcsncmp(ClassName,L"FREEGLUT",wcslen(ClassName))==0){
   hWnd2=hWnd;
   return FALSE;
  }
 }
 return TRUE;
}

void display(void){
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 glViewport(0, 0, WIDTH, HEIGHT);
 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();

 gluPerspective(30.0, (double)WIDTH / (double)HEIGHT, 1.0, 1000.0);
 glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

 gluLookAt(150.0,150.0,-150.0,
      0.0,0.0,0.0,
     0.0,1.0,0.0);

 glMaterialfv(GL_FRONT, GL_DIFFUSE, white);
 //回転
 glRotatef(anglex,1.0f,0.0f,0.0f);//X軸を回転
 glutSolidSphere(40.0,16,16);

 glutSwapBuffers();
}
void idle(void){
 anglex+=2.0f;
 Sleep(1);
 glutPostRedisplay();
}
void Init(){
 glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
 glEnable(GL_DEPTH_TEST);
 //ワイヤーフレーム
 glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
}
bool main(int argc, char *argv[]){
 glutInitWindowPosition(pos_x, pos_y);
 glutInitWindowSize(WIDTH, HEIGHT);
 glutInit(&argc, argv);
 glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
 glutCreateWindow("MDI");
 //FreeGlutのウインドウハンドルとウインドウプロシージャを置き換える
 EnumWindows(enumWindowsProc,0);
 hInst = (HINSTANCE)GetWindowLong(hWnd2, GWL_HINSTANCE);
 if(!MyRegisterWC(WndProc2, L"test",(HBRUSH)(COLOR_APPWORKSPACE + 1)))return FALSE;
 if(!MyRegisterWC(DocProc, ChildDoc, (HBRUSH)GetStockObject(WHITE_BRUSH)))return FALSE;
 if(hWnd2){
 WndProc=(WNDPROC)GetWindowLong(hWnd2,GWL_WNDPROC);
 SetWindowLong(hWnd2,GWL_WNDPROC,(LONG)WndProc2);
 }else{
  return false;
 }
 hMenuFirst = LoadMenu(GetModuleHandle(NULL), L"OWNERMENU");
 hMenuFirstWnd = GetSubMenu(hMenuFirst, 0);
 hMenuDoc = LoadMenu(GetModuleHandle(NULL), L"DOCUMENT");
 hMenuDocWnd = GetSubMenu(hMenuDoc, 1);
 //メニューを作成
 if(hMenuFirst){
 SetMenu(hWnd2,hMenuFirst);
 }else{
 return false;
 }
 // コモンコントロール関係の初期化
 InitCommonControls();
 // ステータスバーを作成
 hStatusbar = CreateStatusWindowW(WS_CHILD | WS_VISIBLE | CCS_BOTTOM | SBARS_SIZEGRIP,
   L"メニューの新規作成でウインドウを作成してください。",hWnd2,ID_STATUS);
 MoveWindow(hWnd2,pos_x,pos_y,WIDTH,HEIGHT,1);
 glutDisplayFunc(display);
 glutIdleFunc(idle);
 Init();
 glutMainLoop();
 return true;
}

 

 

 

 

 

最終更新:2014年06月14日 14:40
添付ファイル