Skip to content

Instantly share code, notes, and snippets.

@bg1bgst333
Created June 23, 2024 09:31
Show Gist options
  • Save bg1bgst333/90628308d97add5059562ed6108204f9 to your computer and use it in GitHub Desktop.
Save bg1bgst333/90628308d97add5059562ed6108204f9 to your computer and use it in GitHub Desktop.
CMenu::CreatePopupMenu
// ヘッダのインクルード
// 既定のヘッダ
#include <stdio.h> // C標準入出力
// 独自のヘッダ
#include "MainWindow.h" // CMainWindow
#include "resource.h"
// ウィンドウクラス登録関数RegisterClass.
BOOL CMainWindow::RegisterClass(HINSTANCE hInstance) {
// ウィンドウクラス名は"CMainWindow".
return CWindow::RegisterClass(hInstance, _T("CMainWindow")); // CWindow::RegisterClassでウィンドウクラス名"CMainWindow"を登録.
}
// ウィンドウクラス登録関数RegisterClass.(メニュー名指定バージョン)
BOOL CMainWindow::RegisterClass(HINSTANCE hInstance, LPCTSTR lpctszMenuName) {
// メニュー名はlpctszMenuName.
return CWindow::RegisterClass(hInstance, _T("CMainWindow"), lpctszMenuName); // CWindow::RegisterClassで, ウィンドウクラス名"CMainWindow", メニュー名lpctszMenuNameを登録.
}
// コンストラクタCMainWindow()
CMainWindow::CMainWindow() {
// メンバの初期化.
m_pMainMenu = NULL;
}
// デストラクタ~CMainWindow()
CMainWindow::~CMainWindow() {
// メンバの終了処理.
Destroy(); // Destroyで子ウィンドウの破棄.
}
// ウィンドウ作成関数Create.(ウィンドウクラス名省略バージョン.)
BOOL CMainWindow::Create(LPCTSTR lpctszWindowName, DWORD dwStyle, int x, int y, int iWidth, int iHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance) {
// ウィンドウクラス名は"CMainWindow".
return CWindow::Create(_T("CMainWindow"), lpctszWindowName, dwStyle, x, y, iWidth, iHeight, hWndParent, hMenu, hInstance); // CWindow::Createにウィンドウクラス名"CMainWindow"を指定.
}
// ウィンドウ破棄関数Destroy
BOOL CMainWindow::Destroy() {
// 変数の初期化.
BOOL bRet = FALSE; // bRetをFALSEで初期化.
// DestroyChildrenを分けたので, 自身のウィンドウ破棄は問題ない.
// まず子ウィンドウの破棄.
DestroyChildren();
// 自身のウィンドウ破棄.
bRet = CWindow::Destroy(); // 戻り値をbRetに格納.
// bRetを返す.
return bRet;
}
// 子ウィンドウ破棄関数DestroyChildren
BOOL CMainWindow::DestroyChildren() {
// 変数の初期化.
BOOL bRet = FALSE; // bRetをFALSEで初期化.
// 破棄したらTRUEを返す.
if (bRet) { // TRUEなら.
return TRUE; // TRUEを返す.
}
// 破棄しなければ, CWindowのDestroyChildrenを返す.
return CWindow::DestroyChildren(); // CWindow::DestroyChildrenを返す.
}
// ウィンドウの作成が開始された時.
int CMainWindow::OnCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct) {
// 親クラスのOnCreateを呼ぶ.
int iRet = CWindow::OnCreate(hwnd, lpCreateStruct); // CWindow::OnCreateを呼び, 戻り値をiRetに格納.
m_pMainMenu = GetMenu(); // CWindow::GetMenuでm_pMainMenu取得.
if (m_pMainMenu == NULL) { // メニューハンドルが無い場合は, m_pMainMenuがNULLになる.
m_pMainMenu = new CMenu();
BOOL bRet = m_pMainMenu->CreateMenu();
if (bRet) {
// サブメニュー1の作成.
CMenu* pSubMenu1 = new CMenu();
pSubMenu1->CreatePopupMenu();
pSubMenu1->AppendMenu(MF_STRING, ID_ITEM_1_1, _T("Item1-1(&A)"));
pSubMenu1->AppendMenu(MF_STRING, ID_ITEM_1_2, _T("Item1-2(&B)"));
pSubMenu1->AppendMenu(MF_STRING, ID_ITEM_1_3, _T("Item1-3(&C)"));
pSubMenu1->AppendMenu(MF_STRING, ID_ITEM_1_4, _T("Item1-4(&D)"));
// メインメニューに追加.
m_pMainMenu->AppendMenu(MF_POPUP, (UINT_PTR)pSubMenu1->m_hMenu, _T("Item1"));
// サブメニュー2の作成.
CMenu* pSubMenu2 = new CMenu();
pSubMenu2->CreatePopupMenu();
pSubMenu2->AppendMenu(MF_STRING, ID_ITEM_2_1, _T("Item2-1(&E)"));
pSubMenu2->AppendMenu(MF_STRING, ID_ITEM_2_2, _T("Item2-2(&F)"));
pSubMenu2->AppendMenu(MF_STRING, ID_ITEM_2_3, _T("Item2-3(&G)"));
pSubMenu2->AppendMenu(MF_STRING, ID_ITEM_2_4, _T("Item2-4(&H)"));
// メインメニューに追加.
m_pMainMenu->AppendMenu(MF_POPUP, (UINT_PTR)pSubMenu2->m_hMenu, _T("Item2"));
// サブメニュー3の作成.
CMenu* pSubMenu3 = new CMenu();
pSubMenu3->CreatePopupMenu();
pSubMenu3->AppendMenu(MF_STRING, ID_ITEM_3_1, _T("Item3-1(&I)"));
pSubMenu3->AppendMenu(MF_STRING, ID_ITEM_3_2, _T("Item3-2(&J)"));
pSubMenu3->AppendMenu(MF_STRING, ID_ITEM_3_3, _T("Item3-3(&K)"));
pSubMenu3->AppendMenu(MF_STRING, ID_ITEM_3_4, _T("Item3-4(&L)"));
// メインメニューに追加.
m_pMainMenu->AppendMenu(MF_POPUP, (UINT_PTR)pSubMenu3->m_hMenu, _T("Item3"));
SetMenu(m_pMainMenu); // CWindow::SetMenuでm_pMainMenuをセット.
}
}
return iRet; // iRetを返す.
}
// ウィンドウが破棄された時.
void CMainWindow::OnDestroy() {
// メニューの終了処理.
CMenu::DeleteMenuHandleMap();
m_pMainMenu = NULL;
// CWindowのOnDestroyを呼ぶ.
CWindow::OnDestroy(); // CWindow::OnDestroyを呼ぶ.
}
// ウィンドウのサイズが変更された時.
void CMainWindow::OnSize(UINT nType, int cx, int cy) {
}
// ウィンドウが閉じられる時.
int CMainWindow::OnClose() {
// メッセージボックスで"Close CMainWindow OK?"と表示.
int iRet = MessageBox(m_hWnd, _T("Close CMainWindow OK?"), _T("CMenu"), MB_OKCANCEL); // MessageBoxで"Close CMainWindow OK?"と表示し, 戻り値をiRetに格納.
if (iRet != IDOK) { // OK以外.(Cancelなど.)
return -1; // -1を返す.
}
// このウィンドウの破棄.(OnCloseの後, ウィンドウの破棄処理が勝手に行われるので, Destroyは不要なのでコメントアウト.)
//Destroy(); // Destroyでこのウィンドウの破棄処理.
// OKなので閉じる.
return CWindow::OnClose(); // 親クラスのOnCloseを呼ぶ.(親クラスのOnCloseは常に閉じる処理になっている.)
}
// ヘッダのインクルード
// 独自のヘッダ
#include "Menu.h" // CMenu
// staticメンバ変数の定義.
std::map<HMENU, CMenu*> CMenu::m_mapMenuHandleMap; // メニューハンドルマップm_mapMenuHandleMap.
// コンストラクタCMenu
CMenu::CMenu() {
// メンバの初期化
m_hMenu = NULL; // m_hMenuをNULLで初期化.
}
// 渡されたメニューハンドルを持つCMenuオブジェクトポインタを返す.
CMenu* CMenu::FromHandle(HMENU hMenu) {
// hMenuでポインタ引けたら返す, 無かったらオブジェクト生成し, ハンドルをセットして, マップに登録.
if (CMenu::m_mapMenuHandleMap.find(hMenu) != CMenu::m_mapMenuHandleMap.end()) {
return CMenu::m_mapMenuHandleMap[hMenu];
}
else {
CMenu* pMenu = new CMenu();
pMenu->m_hMenu = hMenu;
CMenu::m_mapMenuHandleMap[hMenu] = pMenu;
return pMenu;
}
}
// メニューハンドルマップの削除.
void CMenu::DeleteMenuHandleMap() {
// メニューハンドルマップの全削除.
std::map<HMENU, CMenu*>::iterator itor = m_mapMenuHandleMap.begin();
while (itor != m_mapMenuHandleMap.end()) {
HMENU hMenu = itor->first;
CMenu* pMenu = itor->second;
DestroyMenu(hMenu);
delete pMenu;
itor++;
}
m_mapMenuHandleMap.clear();
}
// 指定位置のサブメニューハンドル取得.
HMENU CMenu::GetSubMenuHandle(int nPos) {
// m_hMenuの位置nPosのサブメニューハンドルを返す.
return ::GetSubMenu(m_hMenu, nPos); // GetSubMenuの戻り値を返す.
}
// 指定位置のサブメニューオブジェクトポインタ取得.
CMenu* CMenu::GetSubMenu(int nPos) {
// ハンドル取得して, そこからポインタ取得.
HMENU hMenu = GetSubMenuHandle(nPos);
return FromHandle(hMenu);
}
// アイテムの追加.
BOOL CMenu::AppendMenu(UINT nFlags, UINT_PTR nIDNewItem, LPCTSTR lpszNewItem) {
// 指定位置にアイテム追加.
return ::AppendMenu(m_hMenu, nFlags, nIDNewItem, lpszNewItem);
}
// メニューリソースのロード.
BOOL CMenu::LoadMenu(HINSTANCE hInstance, UINT nIDResource) {
// ロードしてからメニューハンドルマップに登録.
HMENU hNew = ::LoadMenu(hInstance, MAKEINTRESOURCE(nIDResource));
if (hNew != NULL) { // ロード成功.
std::map<HMENU, CMenu*>::iterator itor;
itor = CMenu::m_mapMenuHandleMap.find(m_hMenu);
if (itor != CMenu::m_mapMenuHandleMap.end()) { // 古いのが登録済み.
if (this == itor->second) { // 同じはず.
CMenu::m_mapMenuHandleMap.erase(itor);
DestroyMenu(m_hMenu);
m_hMenu = hNew;
CMenu::m_mapMenuHandleMap[m_hMenu] = this;
return TRUE;
}
}
else { // 登録されてない.
m_hMenu = hNew;
CMenu::m_mapMenuHandleMap[m_hMenu] = this;
return TRUE;
}
}
return FALSE;
}
// メニューの作成.
BOOL CMenu::CreateMenu() {
// 作成してからメニューハンドルマップに登録.
HMENU hNew = ::CreateMenu();
if (hNew != NULL) { // 作成成功.
std::map<HMENU, CMenu*>::iterator itor;
itor = CMenu::m_mapMenuHandleMap.find(m_hMenu);
if (itor != CMenu::m_mapMenuHandleMap.end()) { // 古いのが登録済み.
if (this == itor->second) { // 同じはず.
CMenu::m_mapMenuHandleMap.erase(itor);
DestroyMenu(m_hMenu);
m_hMenu = hNew;
CMenu::m_mapMenuHandleMap[m_hMenu] = this;
return TRUE;
}
}
else { // 登録されてない.
m_hMenu = hNew;
CMenu::m_mapMenuHandleMap[m_hMenu] = this;
return TRUE;
}
}
return FALSE;
}
// ポップアップメニューの作成.
BOOL CMenu::CreatePopupMenu() {
// 作成してからメニューハンドルマップに登録.
HMENU hNew = ::CreatePopupMenu();
if (hNew != NULL) { // 作成成功.
std::map<HMENU, CMenu*>::iterator itor;
itor = CMenu::m_mapMenuHandleMap.find(m_hMenu);
if (itor != CMenu::m_mapMenuHandleMap.end()) { // 古いのが登録済み.
if (this == itor->second) { // 同じはず.
CMenu::m_mapMenuHandleMap.erase(itor);
DestroyMenu(m_hMenu);
m_hMenu = hNew;
CMenu::m_mapMenuHandleMap[m_hMenu] = this;
return TRUE;
}
}
else { // 登録されてない.
m_hMenu = hNew;
CMenu::m_mapMenuHandleMap[m_hMenu] = this;
return TRUE;
}
}
return FALSE;
}
// 二重インクルード防止
#ifndef __MENU_H__
#define __MENU_H__
// ヘッダのインクルード
// 既定のヘッダ
#include <windows.h> // 標準WindowsAPI
#include <map> // std::map
// メニュークラスCMenuの定義
class CMenu {
// publicメンバ
public:
// publicメンバ変数
HMENU m_hMenu; // メニューハンドルm_hMenu
// staticメンバ変数
static std::map<HMENU, CMenu*>m_mapMenuHandleMap; // メニューハンドルをキー, CMenuオブジェクトポインタを値とするマップm_mapMenuHandleMap.
// publicメンバ関数
// コンストラクタ
CMenu(); // コンストラクタCMenu
// staticメンバ関数
static CMenu* FromHandle(HMENU hMenu); // 渡されたメニューハンドルを持つCMenuオブジェクトポインタを返す.
static void DeleteMenuHandleMap(); // メニューハンドルマップの削除.
// メンバ関数
HMENU GetSubMenuHandle(int nPos); // 指定位置のサブメニューハンドル取得.
CMenu* GetSubMenu(int nPos); // 指定位置のサブメニューオブジェクトポインタ取得.
BOOL AppendMenu(UINT nFlags, UINT_PTR nIDNewItem = 0, LPCTSTR lpszNewItem = NULL); // アイテムの追加.
BOOL LoadMenu(HINSTANCE hInstance, UINT nIDResource); // メニューリソースのロード.
BOOL CreateMenu(); // メニューの作成.
BOOL CreatePopupMenu(); // ポップアップメニューの作成.
};
#endif
#include <windows.h>
#define IDM_MAINMENU 100
#define ID_ITEM_1_1 10101
#define ID_ITEM_1_2 10102
#define ID_ITEM_1_3 10103
#define ID_ITEM_1_4 10104
#define ID_ITEM_2_1 10201
#define ID_ITEM_2_2 10202
#define ID_ITEM_2_3 10203
#define ID_ITEM_2_4 10204
#define ID_ITEM_3_1 10301
#define ID_ITEM_3_2 10302
#define ID_ITEM_3_3 10303
#define ID_ITEM_3_4 10304
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment