いつもお世話になっています。
最近は学習がてら遊び半分でソフトウェア作りに励んでいる今日この頃ですが
さぁ問題が発生しました。
お題は「ウィンドウを分割してツリービューとタブをつくり、テキストエディタをつくる」という
ものなのです。
Googleをフル活用し調べ、いろいろなところからソースを拝借してつくっていますが
なんかマズいことに。
main.cpp
/*Lunaスタイルの適応*/
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
/*WindowsXPへの適応*/
#define _WIN32_WINNT 0x0501
/*ヘッダファイルのインクルード*/
#include <windows.h>
#include "resource.h"
#include <commctrl.h>
#include "header.h"
#include <windowsx.h>
/*Libファイルのリンク*/
#pragma comment(lib, "comctl32.lib") // ツリービューの作成に必要
/*リテラル定義*/
#define SPLIT_WIDTH 2
#define SPLIT_MIN 50
/*グローバル変数*/
HINSTANCE hInst; // 現在のインターフェイス
int width = 100; // 分割ウインドウ(左)の幅
/*ウィンドウハンドル*/
HWND hTree;
HWND hEdit;
HWND hCombo1; // コンボボックスのハンドル
HWND hToolBar; // ツールバーのウィンドウハンドル
HWND hRebar; // レバーコントロールのハンドル
HWND hStatus;
HWND hTab; // タブコントロールのハンドル
HWND hRichEdit; // ウィンドウハンドル
WNDPROC defProc;
// リッチエディットの使用するために用いる変数宣言
TCHAR strPath[MAX_PATH + 1]; // DLLのパス
HINSTANCE hRtLib; // インスタンスハンドル
// TBBUTTON(ツールバーボタン)型の配列
TBBUTTON tbButton[] = {
{ STD_FILEOPEN, ID_BUTTON1, TBSTATE_ENABLED, TBSTYLE_BUTTON | BTNS_AUTOSIZE, 0, 0, 0},
{ STD_FILESAVE, ID_BUTTON2, TBSTATE_ENABLED, TBSTYLE_BUTTON | BTNS_AUTOSIZE, 0, 0, 0},
{ STD_COPY, ID_BUTTON3, TBSTATE_ENABLED, TBSTYLE_BUTTON | BTNS_AUTOSIZE, 0, 0, 0},
{ STD_CUT, ID_BUTTON4, TBSTATE_ENABLED, TBSTYLE_BUTTON | BTNS_AUTOSIZE, 0, 0, 0},
{ STD_DELETE, ID_BUTTON5, TBSTATE_ENABLED, TBSTYLE_BUTTON | BTNS_AUTOSIZE, 0, 0, 0},
{ STD_PASTE, ID_BUTTON6, TBSTATE_ENABLED, TBSTYLE_BUTTON | BTNS_AUTOSIZE, 0, 0, 0},
{ STD_REDOW, ID_BUTTON7, TBSTATE_ENABLED, TBSTYLE_BUTTON | BTNS_AUTOSIZE, 0, 0, 0},
{ STD_UNDO, ID_BUTTON8, TBSTATE_ENABLED, TBSTYLE_BUTTON | BTNS_AUTOSIZE, 0, 0, 0}
};
TBBUTTON tbSPACE = {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0L};
/* コールバック関数/初期化関数 */
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK ToolbarProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
/* 独自定義関数 */
int MaxMinPoint(LPARAM, RECT);
void AddItemTree();
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
MyRegisterClass(hInstance);
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInst ,MAKEINTRESOURCE(ICON));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_MENU);
wcex.lpszClassName = TEXT("TheText");
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(ICON));
return RegisterClassEx(&wcex);
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // グローバル変数にインスタンス処理を格納します。
hWnd = CreateWindow(TEXT("ThaText"),TEXT("TheText") , WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
RECT rc;
static BOOL push = FALSE;
RECT Rect; // RECT構造体
static RECT winRect,staRect;
INITCOMMONCONTROLSEX ic; // INITCOMMONCONTROLSEX構造体
REBARBANDINFO rbBand; // REBARBANDINFO構造体
HFONT hFont; // フォント
LPCTSTR szBuf_edit1;
LPCTSTR strItem1[] = {
TEXT("COM1") ,
TEXT("COM2") ,
TEXT("COM3")
};
UINT i;
UINT index;
UINT com_no;
TBADDBITMAP tb;
int nTab;
static RECT Tabrc;
TCITEM ti;
LPMINMAXINFO lpmm;
switch (msg)
{
case WM_CREATE:
InitCommonControls(); //コモンコントロール初期化処理
hTree = CreateWindowEx(WS_EX_CLIENTEDGE, // 拡張ウィンドウスタイル
WC_TREEVIEW,
TEXT(""),
WS_CHILD | WS_BORDER | WS_VISIBLE | TVS_HASLINES |
TVS_HASBUTTONS | TVS_LINESATROOT,
0, 0,
0, 0,
hWnd,
(HMENU)IDC_TREE,
hInst,
NULL);
hTab = CreateWindowEx(0,
WC_TABCONTROL, TEXT(""),
WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE ,
0, 0, 0, 0,
hWnd, (HMENU)ID_TAB, hInst, NULL);
hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, // 拡張ウィンドウスタイル
TEXT("EDIT"),
TEXT("ここに入力"),
WS_CHILD | WS_VISIBLE | ES_WANTRETURN | ES_MULTILINE |
ES_AUTOVSCROLL | WS_VSCROLL | ES_AUTOHSCROLL | WS_HSCROLL,
0, 0,
0, 0,
hWnd,
(HMENU)IDC_EDIT2,
hInst,
NULL);
Edit_LimitText(hEdit,NULL);
AddItemTree(); //ツリービューに要素を挿入
//コモンコントロールの初期化
ic.dwICC = ICC_COOL_CLASSES | ICC_BAR_CLASSES;
ic.dwSize = sizeof(INITCOMMONCONTROLSEX);
InitCommonControlsEx(&ic);
//レバーコントロールの作成
hRebar = CreateWindowEx(0,REBARCLASSNAME,TEXT(""),
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |WS_CLIPCHILDREN | CCS_NODIVIDER,
0, 0, 0, 0,
hWnd, (HMENU)ID_COOL,
(HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL);
// REBARBANDINFO構造体
ZeroMemory(&rbBand, sizeof(REBARBANDINFO));
// 構造体のサイズ
rbBand.cbSize = sizeof(REBARBANDINFO);
// マスクフラグ
rbBand.fMask = RBBIM_STYLE | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_SIZE | RBBIM_BACKGROUND;
// バンドの背景
rbBand.hbmBack = LoadBitmap((HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE),
MAKEINTRESOURCE(IDB_BITMAP1));
// バンドのスタイルフラグ
rbBand.fStyle = RBBS_CHILDEDGE;
// 最小値の高さ
rbBand.cyMinChild = 21;
// 最小値の幅
rbBand.cxMinChild = 100;
// レバーコントロールにのせる対象の子ウインドウのハンドル
hFont = CreateFont(12, 0, 0, 0,
FW_NORMAL, FALSE, FALSE, FALSE,
SHIFTJIS_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,
FF_MODERN,
TEXT("MS Pゴシック"));
hCombo1 = CreateWindowEx(0, TEXT("COMBOBOX"), TEXT(""),
WS_CHILD | WS_VISIBLE | CBS_DROPDOWN,
0, 0, 0, 0,
hRebar, (HMENU)ID_COMBO1,
(HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE) ,NULL);
SendMessage(hCombo1, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(true, 0));
// コンボボックスにデータを詰めていく
for (i = 0 ; i < 3 ; i++)
{
SendMessage(hCombo1 , CB_ADDSTRING , 0 , (LPARAM)strItem1[i]);
}
// ウインドウ生成時にはじめに表示するデータを指定
index = SendMessage(hCombo1, CB_FINDSTRINGEXACT, -1, (LPARAM)TEXT("COM1"));
SendMessage(hCombo1, CB_SETCURSEL, index, 0);
rbBand.hwndChild = hCombo1;
// レバーコントロールにコンボボックス1を挿入
SendMessage(hRebar, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbBand);
// レバーコントロールにツールバーを挿入
hToolBar = CreateWindowEx(
0, //拡張スタイルなし
TOOLBARCLASSNAME, // クラスネーム
NULL, //ウィンドウタイトル
WS_CHILD
| WS_VISIBLE
| CCS_NODIVIDER
| CCS_NORESIZE
| TBSTYLE_FLAT, //ウィンドウスタイル
0, 0, //ウィンドウ位置
0, 0, //ウィンドウ幅、高さ
hRebar, //親ウィンドウ
(HMENU)IDW_TOOL, //コントロール識別子
(HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE) , //インスタンスハンドル
NULL); //pointer to window-creation data
tb.hInst = HINST_COMMCTRL; // ボタンをシステム定義のビットマップ
tb.nID = IDB_STD_SMALL_COLOR; // システム標準ビットマップ(小)
SendMessage(hToolBar, TB_ADDBITMAP, 0, (LPARAM)&tb);
/* TBBUTTON 構造体のサイズを設定 */
SendMessage(hToolBar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
/* ツールバーにボタンを挿入 */
SendMessage(hToolBar, TB_ADDBUTTONS, (WPARAM)9, (LPARAM)(LPTBBUTTON)&tbButton);
// ボタンの区切りを挿入
SendMessage(hToolBar, TB_INSERTBUTTON, 2, (LPARAM)&tbSPACE);
/* ツールバーサブクラス化 */
defProc = (WNDPROC)GetWindowLong(hToolBar, GWL_WNDPROC);
SetWindowLong(hToolBar, GWL_WNDPROC, (LONG)ToolbarProc);
SetWindowLong(hToolBar, GWL_USERDATA, (LONG)defProc);
rbBand.hwndChild = hToolBar;
GetClientRect(hRebar, &Rect);
rbBand.cx = Rect.right - 100;
SendMessage(hRebar, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbBand);
GetWindowRect(hRebar,&winRect);
GetWindowRect(hStatus,&staRect);
// ステータスバーを作成
hStatus = CreateStatusWindow(
WS_CHILD | WS_VISIBLE | CCS_BOTTOM | SBARS_SIZEGRIP,
"",
hWnd,
ID_STATUS
);
SendMessage(hTab, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), 0);
ti.mask = TCIF_TEXT;
ti.pszText = TEXT("タブ0");
TabCtrl_InsertItem(hTab, 0, &ti);
ti.pszText = TEXT("タブ1");
TabCtrl_InsertItem(hTab, 1, &ti);
ti.pszText = TEXT("タブ2");
TabCtrl_InsertItem(hTab, 2, &ti);
break;
case WM_SIZE:
MoveWindow(hTree, 0, winRect.bottom - winRect.top, width - SPLIT_WIDTH, HIWORD(lParam), TRUE);
MoveWindow(hEdit, width + SPLIT_WIDTH + 20 , winRect.bottom - winRect.top + 40, LOWORD(lParam)-300, HIWORD(lParam) - 120 , TRUE);
GetClientRect(hWnd, &Tabrc);
//TabCtrl_AdjustRect(hTab, FALSE, &Tabrc);
/* MoveWindow(hEdit2, width + SPLIT_WIDTH, winRect.bottom - winRect.top, LOWORD(lParam), HIWORD(lParam), TRUE);*/
MoveWindow(hTab, width + SPLIT_WIDTH, winRect.bottom - winRect.top, LOWORD(lParam), HIWORD(lParam), TRUE);
SendMessage(hRebar, WM_SIZE, wParam, lParam);
SendMessage(hStatus, WM_SIZE, wParam, lParam );
//InvalidateRect(hEdit1, NULL, TRUE);
//InvalidateRect(hEdit2, NULL, TRUE);
break;
case WM_LBUTTONDOWN: // マウスの左ボタンが押されたとき
// マウスキャプチャを開始する
SetCapture(hWnd);
SetCursor(LoadCursor(NULL, IDC_SIZEWE));
push = TRUE; // 左ボタンが押された
break;
case WM_LBUTTONUP: // マウスの左ボタンが離されたとき
GetWindowRect(hWnd, &rc);
// マウスカーソルの位置を取得して、終点として保存しておく
width = MaxMinPoint(lParam, rc);
push = FALSE; // 左ボタンが押されてない
// マウスキャプチャを終了する
ReleaseCapture();
PostMessage(hWnd, WM_SIZE, SIZE_RESTORED,
((rc.bottom-rc.top)<<16) | (rc.right-rc.left));
break;
case WM_MOUSEMOVE: // マウスカーソルが移動したとき
if(push == TRUE)
{
GetWindowRect(hWnd, &rc);
// マウスカーソルの位置を取得して、終点として保存しておく
width = MaxMinPoint(lParam, rc);
PostMessage(hWnd, WM_SIZE, SIZE_RESTORED,
((rc.bottom-rc.top)<<16) | (rc.right-rc.left));
}
else if((width <= (LOWORD(lParam) + SPLIT_WIDTH))
&& (width >= (LOWORD(lParam) - SPLIT_WIDTH)))
{
SetCursor(LoadCursor(NULL, IDC_SIZEWE));
}
else
{
SetCursor(LoadCursor(NULL, IDC_ARROW));
}
break;
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// 選択されたメニューの解析:
switch (wmId)
{
case ID_COMBO1:
if (HIWORD(wParam) == CBN_SELCHANGE)
{
// 現在のコンボボックスのデータを取得
com_no = (UINT)SendMessage(hCombo1, CB_GETCURSEL, 0, 0);
// テキストの表示
szBuf_edit1 = strItem1[com_no];
MessageBox(hWnd, szBuf_edit1, TEXT("メッセージ"), MB_OK);
}
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, msg, wParam, lParam);
}
break;
//case WM_NOTIFY:
// switch (((NMHDR *)lParam)->code) {
// case TCN_SELCHANGE:
// InvalidateRect(hTab, NULL, TRUE);
// nTab = TabCtrl_GetCurSel(hTab);
// break;
// case TCN_SELCHANGING:
// nTab = TabCtrl_GetCurSel(hTab);
// break;
// }
// break;
//case WM_GETMINMAXINFO:
// lpmm = (LPMINMAXINFO)lParam;
// lpmm->ptMinTrackSize.x = X_MIN;
// lpmm->ptMinTrackSize.y = Y_MIN;
// break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, msg, wParam, lParam);
}
return 0;
}
int MaxMinPoint(LPARAM lParam,RECT rc)
{
POINTS pts;
pts = MAKEPOINTS(lParam);
width = pts.x;
if(width < SPLIT_MIN)
{
width = SPLIT_MIN;
}
else if(width > (rc.right - rc.left - SPLIT_MIN -10))
{
width = rc.right - rc.left - SPLIT_MIN -10;
}
else
{
;
}
return width;
}
void AddItemTree(){
HTREEITEM hParent1, hParent2, hParent3, hChild1, hChild2;
TV_INSERTSTRUCT tv;
tv.hInsertAfter = TVI_LAST;
tv.item.mask = TVIF_TEXT;
tv.hParent = TVI_ROOT;
tv.item.pszText = TEXT("親1");
hParent1 = TreeView_InsertItem(hTree, &tv);
tv.item.pszText = TEXT("親2");
hParent2 = TreeView_InsertItem(hTree, &tv);
tv.item.pszText = TEXT("親3");
hParent3 = TreeView_InsertItem(hTree, &tv);
tv.hParent = hParent1;
tv.item.pszText = TEXT("子1");
hChild1 = TreeView_InsertItem(hTree, &tv);
tv.item.pszText = TEXT("子2");
hChild2 = TreeView_InsertItem(hTree, &tv);
tv.hParent = hChild1;
tv.item.pszText = TEXT("孫1");
TreeView_InsertItem(hTree, &tv);
tv.hParent = hChild1;
tv.item.pszText = TEXT("孫2");
TreeView_InsertItem(hTree, &tv);
tv.hParent = hParent2;
tv.item.pszText = TEXT("子3");
TreeView_InsertItem(hTree, &tv);
tv.hParent = hParent3;
tv.item.pszText = TEXT("子4");
TreeView_InsertItem(hTree, &tv);
}
/* ツールバーサブクラス */
/* WindowsXPにおいて、
ツールバーのボタン上でマウスの左ボタンを押したまま右ボタンを押すと、
それ以降のマウス操作を正常に受け付けなくなる。 */
LRESULT CALLBACK ToolbarProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_RBUTTONDOWN:
case WM_RBUTTONUP:
if (SendMessage(hWnd, TB_GETHOTITEM, 0, 0) >= 0){
ReleaseCapture();
}
return 0;
}
return CallWindowProc(defProc, hWnd, msg, wParam, lParam);
}
#define IDC_TREE 1001
#define IDC_EDIT2 1002
#define IDM_ABOUT 104
#define IDM_EXIT 105
#define IDC_HP 109
#define IDW_TOOL 149
#define ID_COOL 150
#define ID_COMBO1 165
#define ID_COMBO2 166
#define IDC_COMBO1 161
#define IDC_COMBO2 162
#define ID_BUTTON1 151
#define ID_BUTTON2 152
#define ID_BUTTON3 153
#define ID_BUTTON4 154
#define ID_BUTTON5 155
#define ID_BUTTON6 156
#define ID_BUTTON7 157
#define ID_BUTTON8 158
#define ID_STATUS 2005
#define ID_TAB 1008
#define IDC_RICHEDIT 158
#ifndef IDC_STATIC
#define IDC_STATIC (-1)
#endif
#define IDM_ABOUT 104
#define IDM_EXIT 105
#define IDC_MENU 110
#define IDB_BITMAP1 111
#define DOTMAIL_ICON 112
#define DOTMAIL_SMALL 114
// Generated by ResEdit 1.5.9
// Copyright (C) 2006-2011
// http://www.resedit.net
#include <windows.h>
#include <commctrl.h>
#include <richedit.h>
#include "resource.h"
//
// Bitmap resources
//
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDB_BITMAP1 BITMAP ".\\reber.bmp"
//
// Menu resources
//
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDC_MENU MENU
BEGIN
POPUP "ファイル(&F)"
BEGIN
MENUITEM "アプリケーションの終了(&X)", IDM_EXIT
END
POPUP "ヘルプ(&H)"
BEGIN
MENUITEM "バージョン情報(&A)...", IDM_ABOUT
END
END
見てのとおりインコのWIndowsSDKさんから拝借しています。
しかし、画面を分割したところの境界線をドラッグすると
テキストエリアの体裁がおかしくなります。
おそらくMoveWindow関数がうまく機能していないとめぼしをつけたのですが
なにぶんお馬鹿なゆえ直し方がわかりません・・・
どなたか教えてください
お願いします