• R/O
  • HTTP
  • SSH
  • HTTPS

提交

標籤
無標籤

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Tera Termの個人的な作業用リポジトリ


Commit MetaInfo

修訂20b51fb0784b4095e999b86081418c89e9c0b76d (tree)
時間2022-06-24 23:04:22
作者zmatsuo <zmatsuo@user...>
Commiterzmatsuo

Log Message

ツリー付きプロパティーに拡張した

- TTCPropSheetDlg をツリー付きにできるようにした

git-svn-id: svn+ssh://svn.osdn.net/svnroot/ttssh2/trunk@10016 f5f01b69-1e22-0410-acbf-894ab4bd6246

Change Summary

差異

--- a/teraterm/common/tmfc_propdlg.cpp
+++ b/teraterm/common/tmfc_propdlg.cpp
@@ -26,24 +26,152 @@
2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2727 */
2828
29+#include <windows.h>
30+#include <commctrl.h>
31+#include <wchar.h>
32+#define _CRTDBG_MAP_ALLOC
33+#include <stdlib.h>
34+#include <crtdbg.h>
35+
2936 #include "ttlib.h"
3037 #include "dlglib.h"
3138
3239 #include "tmfc_propdlg.h"
3340
3441 #define REWRITE_TEMPLATE 1
42+#define TREE_WIDTH 200
43+#define CONTROL_SPACE 5
44+
45+BOOL TTCPropSheetDlg::m_TreeViewInit = FALSE;
46+
3547 // quick hack :-(
36-HINSTANCE TTCPropSheetDlg::ghInstance;
3748 class TTCPropSheetDlg* TTCPropSheetDlg::gTTCPS;
3849
50+TTCPropSheetDlg::TTCPropSheetDlg(HINSTANCE hInstance, HWND hParentWnd, const wchar_t *uilangfile)
51+{
52+ m_hInst = hInstance;
53+ m_hWnd = 0;
54+ m_hParentWnd = hParentWnd;
55+ m_UiLanguageFile = _wcsdup(uilangfile);
56+ memset(&m_psh, 0, sizeof(m_psh));
57+ m_psh.dwSize = sizeof(m_psh);
58+ m_psh.dwFlags = PSH_DEFAULT | PSH_NOAPPLYNOW | PSH_USECALLBACK;
59+ //m_psh.dwFlags |= PSH_PROPTITLE; // 「のプロパティー」が追加される?
60+ m_psh.hwndParent = hParentWnd;
61+ m_psh.hInstance = hInstance;
62+ m_psh.pfnCallback = PropSheetProc;
63+ m_Page = NULL;
64+ m_PageCount = 0;
65+ m_TreeView = m_TreeViewInit;
66+}
67+
68+TTCPropSheetDlg::~TTCPropSheetDlg()
69+{
70+ free((void*)m_psh.pszCaption);
71+ free(m_UiLanguageFile);
72+
73+ for (int i = 0; i < m_PageCount; i++) {
74+ free(m_Page[i].path);
75+ m_Page[i].path = NULL;
76+ }
77+ free(m_Page);
78+}
79+
80+void TTCPropSheetDlg::SetTreeViewMode(BOOL enable)
81+{
82+ m_TreeViewInit = enable;
83+}
84+
85+void TTCPropSheetDlg::AddPage(HPROPSHEETPAGE hpage, const wchar_t *path)
86+{
87+ TTPropSheetPage *p =
88+ (TTPropSheetPage *)realloc(m_Page, sizeof(TTPropSheetPage) * (m_PageCount + 1));
89+ if (p == NULL) {
90+ return;
91+ }
92+ m_Page = p;
93+ m_Page[m_PageCount].hPsp = hpage;
94+ m_Page[m_PageCount].path = (path == NULL) ? NULL : _wcsdup(path);
95+ m_PageCount++;
96+}
97+
98+void TTCPropSheetDlg::SetCaption(const wchar_t* caption)
99+{
100+ free((void*)m_psh.pszCaption);
101+ m_psh.pszCaption = _wcsdup(caption);
102+}
103+
104+INT_PTR TTCPropSheetDlg::DoModal()
105+{
106+ INT_PTR result;
107+ int i;
108+ HPROPSHEETPAGE *hPsp = (HPROPSHEETPAGE *)malloc(sizeof(HPROPSHEETPAGE) * m_PageCount);
109+ for(i = 0; i < m_PageCount; i++) {
110+ hPsp[i] = m_Page[i].hPsp;
111+ }
112+ m_psh.nPages = m_PageCount;
113+ m_psh.phpage = hPsp;
114+ gTTCPS = this;
115+ result = PropertySheetW(&m_psh);
116+ free(hPsp);
117+ return result;
118+}
119+
39120 LRESULT CALLBACK TTCPropSheetDlg::WndProc(HWND dlg, UINT msg, WPARAM wParam, LPARAM lParam)
40121 {
41122 switch(msg){
42123 case WM_INITDIALOG:
43124 case WM_SHOWWINDOW: {
125+ if (m_TreeView) {
126+ AddTreeControl();
127+ }
44128 CenterWindow(dlg, m_hParentWnd);
45129 break;
46130 }
131+ case WM_NOTIFY: {
132+ NMHDR *nmhdr = (NMHDR *)lParam;
133+ switch(nmhdr->code) {
134+#if 0
135+ // TVN_SELCHANGED があれば不要、そのうち消す
136+ case TVN_SELCHANGINGW:
137+ case TVN_SELCHANGING: {
138+ NMTREEVIEWW *pnmtv = (LPNMTREEVIEWW)lParam;
139+ TVITEMW item;
140+ item.mask = TVIF_PARAM;
141+ item.hItem = pnmtv->itemNew.hItem;
142+ SendMessageW(m_hWndTV, TVM_GETITEMW, 0, (LPARAM)&item);
143+ WPARAM page_index = item.lParam;
144+ SendMessageW(m_hWnd, PSM_SETCURSEL, page_index, 0);
145+ break;
146+ }
147+#endif
148+ case TVN_SELCHANGEDW:
149+ case TVN_SELCHANGED: {
150+ // ツリービューが選択された、タブを切り替える
151+ NMTREEVIEWW *pnmtv = (LPNMTREEVIEWW)lParam;
152+ TVITEMW item;
153+ item.mask = TVIF_PARAM;
154+ item.hItem = pnmtv->itemNew.hItem;
155+ SendMessageW(m_hWndTV, TVM_GETITEMW, 0, (LPARAM)&item);
156+ WPARAM page_index = item.lParam;
157+ SendMessageW(m_hWnd, PSM_SETCURSEL, page_index, 0);
158+ break;
159+ }
160+ case TCN_SELCHANGE: {
161+ // タブが切り替わるときに発生、ツリービューと同期
162+ // タブをマウスでクリック、
163+ // タブにフォーカスがあるときに左右キー
164+ // CTRL+PgUp,PgDn や CTRL+TABでは発生しない?? TCN_KEYDOWNで処理が必要?
165+ HWND hTab = PropSheet_GetTabControl(dlg);
166+ int cur_sel = TabCtrl_GetCurSel(hTab);
167+ HTREEITEM item = GetTreeItem(cur_sel, TVI_ROOT);
168+ if (TreeView_GetSelection(m_hWndTV) != item) {
169+ TreeView_SelectItem(m_hWndTV, item);
170+ }
171+ break;
172+ }
173+ }
174+ }
47175 }
48176 SetWindowLongPtrW(dlg, GWLP_WNDPROC, m_OrgProc);
49177 SetWindowLongPtrW(dlg, GWLP_USERDATA, m_OrgUserData);
@@ -51,6 +179,23 @@ LRESULT CALLBACK TTCPropSheetDlg::WndProc(HWND dlg, UINT msg, WPARAM wParam, LPA
51179 m_OrgProc = SetWindowLongPtrW(dlg, GWLP_WNDPROC, (LONG_PTR)WndProcStatic);
52180 m_OrgUserData = SetWindowLongPtrW(dlg, GWLP_USERDATA, (LONG_PTR)this);
53181
182+#if 0
183+ // ?? CTRL+PgUp,PgDn ではこのメッセージは発生しない
184+ // そのうち消す
185+ switch(msg){
186+ case PSM_CHANGED:
187+ case PSM_SETCURSEL:
188+ case PSM_SETCURSELID: {
189+ if (m_TreeView) {
190+ HWND hTab = PropSheet_GetTabControl(dlg);
191+ int cur_sel = TabCtrl_GetCurSel(hTab);
192+ int a = 0;
193+ }
194+
195+ break;
196+ }
197+ }
198+#endif
54199 return result;
55200 }
56201
@@ -63,15 +208,16 @@ LRESULT CALLBACK TTCPropSheetDlg::WndProcStatic(HWND dlg, UINT msg, WPARAM wPara
63208 int CALLBACK TTCPropSheetDlg::PropSheetProc(HWND hWnd, UINT msg, LPARAM lp)
64209 {
65210 switch (msg) {
66- case PSCB_PRECREATE:
67- {
211+ case PSCB_PRECREATE: {
68212 #if defined(REWRITE_TEMPLATE)
69213 // テンプレートの内容を書き換える
70214 // http://home.att.ne.jp/banana/akatsuki/doc/atlwtl/atlwtl15-01/index.html
215+ TTCPropSheetDlg*self = gTTCPS;
216+ HINSTANCE hInst = self->m_hInst;
71217 size_t PrevTemplSize;
72218 size_t NewTemplSize;
73219 DLGTEMPLATE *NewTempl =
74- TTGetNewDlgTemplate(ghInstance, (DLGTEMPLATE *)lp,
220+ TTGetNewDlgTemplate(hInst, (DLGTEMPLATE *)lp,
75221 &PrevTemplSize, &NewTemplSize);
76222 NewTempl->style &= ~DS_CONTEXTHELP; // check DLGTEMPLATEEX
77223 memcpy((void *)lp, NewTempl, NewTemplSize);
@@ -79,8 +225,7 @@ int CALLBACK TTCPropSheetDlg::PropSheetProc(HWND hWnd, UINT msg, LPARAM lp)
79225 #endif
80226 break;
81227 }
82- case PSCB_INITIALIZED:
83- {
228+ case PSCB_INITIALIZED: {
84229 static const DlgTextInfo TextInfos[] = {
85230 { IDOK, "BTN_OK" },
86231 { IDCANCEL, "BTN_CANCEL" },
@@ -97,44 +242,227 @@ int CALLBACK TTCPropSheetDlg::PropSheetProc(HWND hWnd, UINT msg, LPARAM lp)
97242 return 0;
98243 }
99244
100-void TTCPropSheetDlg::AddPage(HPROPSHEETPAGE page)
245+static void MoveChildWindows(HWND hWnd, int nDx, int nDy)
101246 {
102- hPsp[m_PageCount] = page;
103- m_PageCount++;
247+ HWND hChildWnd = GetWindow(hWnd, GW_CHILD);
248+ while (hChildWnd != NULL) {
249+ RECT rect;
250+ GetWindowRect(hChildWnd, &rect);
251+ int x = rect.left + nDx;
252+ int y = rect.top + nDy;
253+ POINT p;
254+ p.x = x;
255+ p.y = y;
256+ ScreenToClient(hWnd, &p);
257+ x = p.x;
258+ y = p.y;
259+ SetWindowPos(hChildWnd, NULL, x, y, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
260+
261+ hChildWnd = GetNextWindow(hChildWnd, GW_HWNDNEXT);
262+ }
104263 }
105264
106-TTCPropSheetDlg::TTCPropSheetDlg(HINSTANCE hInstance, HWND hParentWnd, const wchar_t *uilangfile)
265+HTREEITEM TTCPropSheetDlg::GetTreeItem(int nPage, HTREEITEM hParent)
107266 {
108- m_hInst = hInstance;
109- m_hWnd = 0;
110- m_hParentWnd = hParentWnd;
111- m_UiLanguageFile = _wcsdup(uilangfile);
112- memset(&m_psh, 0, sizeof(m_psh));
113- m_psh.dwSize = sizeof(m_psh);
114- m_psh.dwFlags = PSH_DEFAULT | PSH_NOAPPLYNOW | PSH_USECALLBACK;
115- //m_psh.dwFlags |= PSH_PROPTITLE; // 「のプロパティー」が追加される?
116- m_psh.hwndParent = hParentWnd;
117- m_psh.hInstance = hInstance;
118- m_psh.pfnCallback = PropSheetProc;
119- m_PageCount = 0;
267+ HTREEITEM hItem = TreeView_GetChild(m_hWndTV, hParent);
268+ while (hItem) {
269+ TVITEMW item;
270+ item.hItem = hItem;
271+ item.mask = TVIF_PARAM;
272+ TreeView_GetItem(m_hWndTV, &item);
273+
274+ if (item.lParam == nPage) {
275+ // 見つかった
276+ return hItem;
277+ }
278+
279+ // 子
280+ HTREEITEM hItemFound = GetTreeItem(nPage, hItem);
281+ if (hItemFound != NULL) {
282+ // 見つかった
283+ return hItemFound;
284+ }
285+
286+ // 次
287+ hItem = TreeView_GetNextItem(m_hWndTV, hItem, TVGN_NEXT);
288+ }
289+
290+ return NULL;
120291 }
121-TTCPropSheetDlg::~TTCPropSheetDlg()
292+
293+/**
294+ * パスを作成して返す
295+ * 存在していたらそれを返す
296+ * @param path L"path1/path2/path3"
297+ * @param HTREEITEM 呼び出し元はTVI_ROOT (再帰用)
298+ * @param page_index 作成したパスに設定するpage_index(0...)
299+ * @return HTREEITEM
300+ */
301+HTREEITEM TTCPropSheetDlg::CreatePath(const wchar_t *path, HTREEITEM hParent, int page_index)
122302 {
123- free((void*)m_psh.pszCaption);
124- free(m_UiLanguageFile);
303+ if (path == NULL || path[0] == 0) {
304+ return hParent;
305+ }
306+
307+ wchar_t *path_cur = _wcsdup(path);
308+ wchar_t *path_next = NULL;
309+ wchar_t *p = wcschr(path_cur, L'/');
310+ if (p != NULL) {
311+ path_next = p + 1;
312+ *p = 0;
313+ }
314+
315+ // パスが既に存在しているか?
316+ HTREEITEM hItem = TreeView_GetChild(m_hWndTV, hParent);
317+ while (hItem) {
318+ wchar_t text[MAX_PATH];
319+ TVITEMW item;
320+ item.hItem = hItem;
321+ item.mask = TVIF_TEXT;
322+ item.cchTextMax = _countof(text);
323+ item.pszText = text;
324+ // TreeView_GetItem(m_hWndTV, &item);
325+ SendMessageW(m_hWndTV, TVM_GETITEMW, 0, (LPARAM)&item);
326+
327+ if (wcscmp(item.pszText, path_cur) ==0) {
328+ // 存在している
329+ if (path_next != NULL) {
330+ // 再帰、次を探す
331+ hItem = CreatePath(path_next, hItem, page_index);
332+ }
333+ free(path_cur);
334+ return hItem;
335+ }
336+
337+ // 次
338+ hItem = TreeView_GetNextItem(m_hWndTV, hItem, TVGN_NEXT);
339+ }
340+
341+ // 見つからない、作る
342+ TVINSERTSTRUCTW tvi;
343+ tvi.hParent = hParent;
344+ tvi.hInsertAfter = TVI_LAST;
345+ tvi.item.mask = TVIF_TEXT | TVIF_PARAM;
346+ tvi.item.pszText = (wchar_t *)path_cur;
347+ tvi.item.lParam = (LPARAM)page_index;
348+ //TreeView_InsertItem(m_hWndTV, &tvi);
349+ hItem = (HTREEITEM)SendMessageW(m_hWndTV, TVM_INSERTITEMW, 0, (LPARAM)&tvi);
350+
351+ if (path_next != NULL) {
352+ // 再帰で探す(見つからず、作ることになる)
353+ hItem = CreatePath(path_next, hItem, page_index);
354+ }
355+
356+ free(path_cur);
357+ return hItem;
125358 }
126359
127-void TTCPropSheetDlg::SetCaption(const wchar_t* caption)
360+void TTCPropSheetDlg::CreateTree(HWND dlg)
128361 {
129- free((void*)m_psh.pszCaption);
130- m_psh.pszCaption = _wcsdup(caption);
362+ HWND hTab = PropSheet_GetTabControl(dlg);
363+ const int nPageCount = TabCtrl_GetItemCount(hTab);
364+
365+ // シート(木の葉)を追加する
366+ for (int i = 0; i < nPageCount; i++) {
367+ // ページのタイトル取得
368+ wchar_t page_title[MAX_PATH];
369+ TCITEMW ti;
370+ ZeroMemory(&ti, sizeof(ti));
371+ ti.mask = TCIF_TEXT;
372+ ti.cchTextMax = _countof(page_title);
373+ ti.pszText = page_title;
374+ //TabCtrl_GetItem(hTab, i, &ti);
375+ SendMessageW(hTab, TCM_GETITEMW, (WPARAM)i, (LPARAM)&ti);
376+
377+ // パス(枝)を作る
378+ wchar_t *path = m_Page[i].path;
379+ HTREEITEM hItem = CreatePath(path, TVI_ROOT, i);
380+
381+ // シートを追加する
382+ TVINSERTSTRUCTW tvi;
383+ tvi.hParent = hItem;
384+ tvi.hInsertAfter = TVI_LAST;
385+ tvi.item.mask = TVIF_TEXT | TVIF_PARAM;
386+ tvi.item.pszText = page_title;
387+ tvi.item.lParam = (LPARAM)i;
388+ //hItem = TreeView_InsertItem(m_hWndTV, &tvi);
389+ hItem = (HTREEITEM)SendMessageW(m_hWndTV, TVM_INSERTITEMW, 0, (LPARAM)&tvi);
390+ }
131391 }
132392
133-INT_PTR TTCPropSheetDlg::DoModal()
393+void TTCPropSheetDlg::AddTreeControl()
134394 {
135- m_psh.nPages = m_PageCount;
136- m_psh.phpage = hPsp;
137- ghInstance = m_hInst;
138- gTTCPS = this;
139- return PropertySheetW(&m_psh);
395+ HWND hTab = PropSheet_GetTabControl(m_hWnd);
396+
397+ // ツリーで選択できるのでタブは1行設定にする
398+ SetWindowLongPtr(hTab, GWL_STYLE, GetWindowLongPtr(hTab, GWL_STYLE) & ~TCS_MULTILINE);
399+
400+#if 0
401+ // タブを消して領域を移動しようとしたがうまくいかなかった
402+ // そのうちこのブロックは消す
403+ const bool m_HideTab = true;
404+ if (m_HideTab) {
405+ // タブ部分を隠す
406+ ShowWindow(hTab, SW_HIDE);
407+ EnableWindow(hTab, FALSE);
408+
409+ // タブ部分のサイズ(高さ)
410+ RECT item_rect;
411+ TabCtrl_GetItemRect(hTab, 0, &item_rect);
412+ const int item_height = item_rect.bottom - item_rect.top;
413+
414+ // tab controlのタブ分、ダイアログを小さくする
415+ RECT dlg_rect;
416+ GetWindowRect(m_hWnd, &dlg_rect);
417+ int w = dlg_rect.right - dlg_rect.left;
418+ int h = dlg_rect.bottom - dlg_rect.top - item_height;
419+ SetWindowPos(m_hWnd, NULL, 0, 0, w, h, SWP_NOZORDER | SWP_NOMOVE);
420+
421+ // タブコントロールをタブ分上に移動する
422+ RECT tab_rect;
423+ GetWindowRect(hTab, &tab_rect);
424+
425+ POINT start;
426+ start.x = tab_rect.left;
427+ start.y = tab_rect.top - item_height;
428+ ScreenToClient(m_hWnd, &start);
429+ SetWindowPos(hTab, NULL, start.x, start.y, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
430+ }
431+#endif
432+
433+ // ツリーコントロールの位置を決める
434+ RECT tree_rect;
435+ GetWindowRect(hTab, &tree_rect);
436+ int tree_w = TREE_WIDTH;
437+ int tree_h = tree_rect.bottom - tree_rect.top;
438+ POINT pt;
439+ pt.x = tree_rect.left;
440+ pt.y = tree_rect.top;
441+ ScreenToClient(m_hWnd, &pt);
442+
443+ // ツリーコントロール分ダイアログのサイズを大きくする
444+ RECT dlg_rect;
445+ GetWindowRect(m_hWnd, &dlg_rect);
446+ int w = dlg_rect.right - dlg_rect.left + TREE_WIDTH + CONTROL_SPACE;
447+ int h = dlg_rect.bottom - dlg_rect.top;
448+ SetWindowPos(m_hWnd, NULL, 0, 0, w, h, SWP_NOZORDER | SWP_NOMOVE);
449+
450+ // ダイアログのサイズを大きくした分、コントロールを移動する
451+ MoveChildWindows(m_hWnd, TREE_WIDTH + CONTROL_SPACE, 0);
452+
453+ const DWORD dwTreeStyle =
454+ TVS_SHOWSELALWAYS|TVS_TRACKSELECT|TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS;
455+ m_hWndTV = CreateWindowExW(0,
456+ WC_TREEVIEWW,
457+ L"Tree View",
458+ WS_VISIBLE | WS_CHILD | WS_BORDER | WS_TABSTOP | dwTreeStyle,
459+ pt.x,
460+ pt.y,
461+ tree_w,
462+ tree_h,
463+ m_hWnd,
464+ NULL,
465+ m_hInst,
466+ NULL);
467+ CreateTree(m_hWnd);
140468 }
--- a/teraterm/common/tmfc_propdlg.h
+++ b/teraterm/common/tmfc_propdlg.h
@@ -37,26 +37,39 @@ public:
3737 TTCPropSheetDlg(HINSTANCE hInstance, HWND hParentWnd, const wchar_t *uilangfile);
3838 virtual ~TTCPropSheetDlg();
3939 INT_PTR DoModal();
40- void AddPage(HPROPSHEETPAGE page);
40+ void AddPage(HPROPSHEETPAGE page, const wchar_t *path = NULL);
4141 void SetCaption(const wchar_t *caption);
42+ static void SetTreeViewMode(BOOL enable);
4243
4344 private:
45+ HWND m_hWnd;
46+ HWND m_hParentWnd;
47+ HINSTANCE m_hInst;
48+ wchar_t *m_UiLanguageFile;
49+
4450 static int CALLBACK PropSheetProc(HWND hWnd, UINT msg, LPARAM lParam);
4551 static LRESULT CALLBACK WndProcStatic(HWND dlg, UINT msg, WPARAM wParam, LPARAM lParam);
46- static HINSTANCE ghInstance;
4752 static class TTCPropSheetDlg *gTTCPS;
4853 LRESULT CALLBACK WndProc(HWND dlg, UINT msg, WPARAM wParam, LPARAM lParam);
54+ LONG_PTR m_OrgProc;
55+ LONG_PTR m_OrgUserData;
4956
5057 PROPSHEETHEADERW m_psh;
51- HWND m_hWnd;
52- HWND m_hParentWnd;
53- HINSTANCE m_hInst;
54-
5558 int m_PageCount;
56- HPROPSHEETPAGE hPsp[9];
59+ struct TTPropSheetPage {
60+ HPROPSHEETPAGE hPsp;
61+ wchar_t *path;
62+ };
63+ TTPropSheetPage *m_Page;
5764
58- LONG_PTR m_OrgProc;
59- LONG_PTR m_OrgUserData;
65+ // tree control
66+ BOOL m_TreeView;
67+ HWND m_hWndTV;
68+ void AddTreeControl();
69+ void CreateTree(HWND dlg);
70+ HTREEITEM CreatePath(const wchar_t *path, HTREEITEM hParent, int data);
71+ HTREEITEM GetTreeItem(int nPage, HTREEITEM hParent);
6072
61- wchar_t *m_UiLanguageFile;
73+ // 初期値
74+ static BOOL m_TreeViewInit;
6275 };