aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRadAd <adamgates84+github@gmail.com>2019-07-11 16:00:59 +1000
committerRadAd <adamgates84+github@gmail.com>2019-07-11 16:00:59 +1000
commitf9e3c9ef965e5afc0b141693bde74fed24280db6 (patch)
tree5ab56e13ffa2ef10578b52efd5d37336c5d4f35a
parent9bbb22c81d04975e8e2aaeebf98545f86d4716f0 (diff)
downloadRadTerminal-f9e3c9ef965e5afc0b141693bde74fed24280db6.tar.gz
RadTerminal-f9e3c9ef965e5afc0b141693bde74fed24280db6.zip
Create MDI version
-rw-r--r--.gitignore1
-rw-r--r--RadTerminal.cpp302
-rw-r--r--RadTerminal.rcbin0 -> 6640 bytes
-rw-r--r--RadTerminal.vcxproj5
-rw-r--r--RadTerminalFrame.cpp116
-rw-r--r--WinUtils.h46
-rw-r--r--resource.hbin0 -> 2558 bytes
7 files changed, 363 insertions, 107 deletions
diff --git a/.gitignore b/.gitignore
index b2c6157..d62187f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,4 @@ Int/
*.VC.db
*.VC.VC.opendb
*.vcxproj.user
+*.aps
diff --git a/RadTerminal.cpp b/RadTerminal.cpp
index 2993d41..a7bbafc 100644
--- a/RadTerminal.cpp
+++ b/RadTerminal.cpp
@@ -6,6 +6,7 @@
#include "WinUtils.h"
#include "libtsm\src\tsm\libtsm.h"
#include "libtsm\external\xkbcommon\xkbcommon-keysyms.h"
+#include "resource.h"
// TODO
// https://stackoverflow.com/questions/5966903/how-to-get-mousemove-and-mouseclick-in-bash
@@ -28,12 +29,6 @@
// See https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences
// Tabs in frame - see https://docs.microsoft.com/en-au/windows/desktop/dwm/customframe
-#ifdef _UNICODE
-#define tstring wstring
-#else
-#define tstring string
-#endif
-
#define PROJ_NAME TEXT("RadTerminal")
#define PROJ_CODE TEXT("RadTerminal")
@@ -53,24 +48,47 @@ void ShowError(HWND hWnd, LPCTSTR msg, HRESULT hr)
#define CHECK(x, r) \
if (!(x)) \
{ \
- ShowError(hWnd, _T(#x), HRESULT_FROM_WIN32(GetLastError())); \
+ ShowError(hWnd, __FUNCTIONW__ TEXT(": ") TEXT(#x), HRESULT_FROM_WIN32(GetLastError())); \
return (r); \
}
#define CHECK_ONLY(x) \
if (!(x)) \
{ \
- ShowError(hWnd, _T(#x), HRESULT_FROM_WIN32(GetLastError())); \
+ ShowError(hWnd, __FUNCTIONW__ TEXT(": ") TEXT(#x), HRESULT_FROM_WIN32(GetLastError())); \
}
#define VERIFY(x) \
if (!(x)) \
{ \
- ShowError(hWnd, _T(#x), 0); \
+ ShowError(hWnd, __FUNCTIONW__ TEXT(": ") TEXT(#x), 0); \
}
+HWND CreateRadTerminalFrame(HINSTANCE hInstance, int nCmdShow);
LRESULT CALLBACK RadTerminalWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+ATOM RegisterRadTerminal(HINSTANCE hInstance)
+{
+ WNDCLASS wc = {};
+
+ wc.lpfnWndProc = RadTerminalWindowProc;
+ wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ //wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
+ wc.hInstance = hInstance;
+ wc.lpszClassName = PROJ_CODE;
+
+ return RegisterClass(&wc);
+}
+
+ATOM GetRadTerminalAtom(HINSTANCE hInstance)
+{
+ static ATOM g_atom = RegisterRadTerminal(hInstance);
+ return g_atom;
+}
+
+HWND ActionNewWindow(HWND hWnd, bool bParseCmdLine);
+
struct RadTerminalCreate
{
int iFontHeight;
@@ -128,22 +146,8 @@ void ParseCommandLine(RadTerminalCreate& rtc)
}
}
-int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE, PTSTR pCmdLine, int nCmdShow)
+RadTerminalCreate GetDefaultTerminalCreate(bool bParseCmdLine)
{
- HWND hWnd = NULL;
-
- WNDCLASS wc = {};
-
- wc.lpfnWndProc = RadTerminalWindowProc;
- wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
- wc.hCursor = LoadCursor(NULL, IDC_ARROW);
- //wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
- wc.hInstance = hInstance;
- wc.lpszClassName = PROJ_CODE;
-
- ATOM atom = NULL;
- CHECK(atom = RegisterClass(&wc), EXIT_FAILURE);
-
RadTerminalCreate rtc = {};
rtc.iFontHeight = 16;
rtc.strFontFace = _T("Consolas");
@@ -154,28 +158,71 @@ int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE, PTSTR pCmdLine, int nCmdSho
rtc.strCmd = _T("cmd");
LoadRegistry(rtc);
- ParseCommandLine(rtc);
+ if (bParseCmdLine)
+ ParseCommandLine(rtc);
- HWND hChildWnd = CreateWindowEx(
- WS_EX_ACCEPTFILES,
- MAKEINTATOM(atom),
- PROJ_NAME,
- WS_OVERLAPPEDWINDOW | WS_VSCROLL,
- CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
- NULL, // Parent window
- NULL, // Menu
- hInstance,
- &rtc
- );
- CHECK(hChildWnd, EXIT_FAILURE);
+ return rtc;
+}
+
+int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE, PTSTR pCmdLine, int nCmdShow)
+{
+ HWND hWnd = NULL;
+ HWND hWndMDIClient = NULL;
+ HACCEL hAccel = NULL;
+ bool bMDI = true;
+
+ CHECK(GetRadTerminalAtom(hInstance), EXIT_FAILURE);
+
+ if (bMDI)
+ {
+ hWnd = CreateRadTerminalFrame(hInstance, nCmdShow);
+ CHECK(hWnd, EXIT_FAILURE);
+
+ hWndMDIClient = GetMDIClient(hWnd);
+ hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR1));
+
+ HWND hChildWnd = ActionNewWindow(hWnd, true);
+
+ if (true && hChildWnd != NULL)
+ {
+ RECT r = {};
+ GetWindowRect(hChildWnd, &r);
+ UnadjustWindowRectEx(&r, GetWindowStyle(hChildWnd), GetMenu(hChildWnd) != NULL, GetWindowExStyle(hChildWnd));
+ AdjustWindowRectEx(&r, GetWindowStyle(hWnd), GetMenu(hWnd) != NULL, GetWindowExStyle(hWnd));
+ CHECK(SetWindowPos(hWnd, 0, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_NOMOVE | SWP_NOZORDER), FALSE);
+ ShowWindow(hChildWnd, SW_MAXIMIZE);
+ }
+ }
+ else
+ {
+ RadTerminalCreate rtc = GetDefaultTerminalCreate(true);
+
+ hWnd = CreateWindowEx(
+ WS_EX_ACCEPTFILES,
+ MAKEINTATOM(GetRadTerminalAtom(hInstance)),
+ PROJ_NAME,
+ WS_OVERLAPPEDWINDOW | WS_VSCROLL,
+ CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
+ NULL, // Parent window
+ NULL, // Menu
+ hInstance,
+ &rtc
+ );
+ CHECK(hWnd, EXIT_FAILURE);
+
+ ShowWindow(hWnd, nCmdShow);
+ }
- ShowWindow(hChildWnd, nCmdShow);
MSG msg = {};
- while (GetMessage(&msg, NULL, 0, 0))
+ while (GetMessage(&msg, (HWND) NULL, 0, 0))
{
- TranslateMessage(&msg);
- DispatchMessage(&msg);
+ if (!TranslateMDISysAccel(hWndMDIClient, &msg) &&
+ !TranslateAccelerator(hWnd, hAccel, &msg))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
}
return EXIT_SUCCESS;
@@ -252,18 +299,18 @@ struct tsm_screen_draw_data
tsm_screen_draw_state state;
};
-SIZE GetCellSize(const tsm_screen_draw_info* di)
+inline SIZE GetCellSize(const tsm_screen_draw_info* di)
{
return { di->tm.tmAveCharWidth, di->tm.tmHeight };
}
-POINT GetScreenPos(const tsm_screen_draw_info* di, COORD pos)
+inline POINT GetScreenPos(const tsm_screen_draw_info* di, COORD pos)
{
SIZE sz = GetCellSize(di);
return { pos.X * sz.cx, pos.Y * sz.cy };
}
-COORD GetCellPos(const tsm_screen_draw_info* di, POINT pos)
+inline COORD GetCellPos(const tsm_screen_draw_info* di, POINT pos)
{
SIZE sz = GetCellSize(di);
return { (SHORT) (pos.x / sz.cx), (SHORT) (pos.y / sz.cy) };
@@ -477,47 +524,51 @@ BOOL CheckScrollBar(HWND hWnd)
return GetScrollPos(hWnd, SB_VERT) == nPos;
}
-int ActionCopyToClipboard(HWND hWnd)
+// trim empty space from end of lines
+void TrimLines(char* buf, int* plen)
{
- const RadTerminalData* const data = (RadTerminalData*) GetWindowLongPtr(hWnd, GWLP_USERDATA);
- char* buf = nullptr;
- int len = tsm_screen_selection_copy(data->screen, &buf);
- if (len > 0)
+ char* lastnonnull = nullptr;
+ for (int i = 0; i < *plen; ++i)
{
- { // trim empty space from end of lines
- char* lastnonnull = nullptr;
- for (int i = 0; i < len; ++i)
- {
- switch (buf[i])
- {
- case ' ':
- case '\0':
- //buf[i] = ' ';
- break;
-
- case '\n':
- if (lastnonnull != nullptr)
- {
- strncpy_s(lastnonnull, len - (lastnonnull - buf), buf + i, len - i); // TODO len should be len - (lastnonnull - buf) I think
- int cut = (int) ((buf + i) - lastnonnull);
- len -= cut;
- i -= cut;
- }
- // fallthrough
-
- default:
- lastnonnull = buf + i + 1;
- break;
- }
- }
+ switch (buf[i])
+ {
+ case ' ':
+ case '\0':
+ //buf[i] = ' ';
+ break;
+ case '\n':
if (lastnonnull != nullptr)
{
- *lastnonnull = '\0';
- int cut = (int) ((buf + len) - lastnonnull);
- len -= cut;
+ strncpy_s(lastnonnull, *plen - (lastnonnull - buf), buf + i, *plen - i); // TODO len should be *plen - (lastnonnull - buf) I think
+ int cut = (int) ((buf + i) - lastnonnull);
+ *plen -= cut;
+ i -= cut;
}
+ // fallthrough
+
+ default:
+ lastnonnull = buf + i + 1;
+ break;
}
+ }
+
+ if (lastnonnull != nullptr)
+ {
+ *lastnonnull = '\0';
+ int cut = (int) ((buf + *plen) - lastnonnull);
+ *plen -= cut;
+ }
+}
+
+int ActionCopyToClipboard(HWND hWnd)
+{
+ const RadTerminalData* const data = (RadTerminalData*) GetWindowLongPtr(hWnd, GWLP_USERDATA);
+ char* buf = nullptr;
+ int len = tsm_screen_selection_copy(data->screen, &buf);
+ if (len > 0)
+ {
+ TrimLines(buf, &len);
HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, len + 1);
memcpy(GlobalLock(hMem), buf, len + 1);
@@ -604,9 +655,46 @@ int ActionScrollbackDown(HWND hWnd)
return 0;
}
+HWND ActionNewWindow(HWND hWnd, bool bParseCmdLine)
+{
+ const HINSTANCE hInstance = GetWindowInstance(hWnd);
+ const HWND hWndMDIClient = GetMDIClient(hWnd);
+ BOOL bMaximized = FALSE;
+ GetMDIActive(hWndMDIClient, &bMaximized);
+
+ const RadTerminalCreate rtc = GetDefaultTerminalCreate(bParseCmdLine);
+
+ HWND hChildWnd = CreateMDIWindow(
+ MAKEINTATOM(GetRadTerminalAtom(hInstance)),
+ PROJ_NAME,
+ (bMaximized ? WS_MAXIMIZE : 0) | WS_OVERLAPPEDWINDOW | WS_VSCROLL,
+ CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
+ hWndMDIClient, // Parent window
+ hInstance,
+ (LPARAM) &rtc
+ );
+ CHECK(hChildWnd != NULL, NULL);
+
+ SetWindowLong(hChildWnd, GWL_EXSTYLE, GetWindowExStyle(hChildWnd) | WS_EX_ACCEPTFILES);
+
+ ShowWindow(hChildWnd, SW_SHOW);
+ return hChildWnd;
+}
+
+inline LRESULT MyDefWindowProc(_In_ HWND hWnd, _In_ UINT Msg, _In_ WPARAM wParam, _In_ LPARAM lParam)
+{
+ if (IsMDIChild(hWnd))
+ return DefMDIChildProc(hWnd, Msg, wParam, lParam);
+ else
+ return DefWindowProc(hWnd, Msg, wParam, lParam);
+}
+
BOOL RadTerminalWindowOnCreate(HWND hWnd, LPCREATESTRUCT lpCreateStruct)
{
- const RadTerminalCreate* const rtc = (RadTerminalCreate*) lpCreateStruct->lpCreateParams;
+ FORWARD_WM_CREATE(hWnd, lpCreateStruct, MyDefWindowProc);
+
+ MDICREATESTRUCT* mdics = (MDICREATESTRUCT*) lpCreateStruct->lpCreateParams;
+ const RadTerminalCreate* const rtc = IsMDIChild(hWnd) ? (RadTerminalCreate*) mdics->lParam : (RadTerminalCreate*) lpCreateStruct->lpCreateParams;
RadTerminalData* const data = new RadTerminalData;
ZeroMemory(data, sizeof(RadTerminalData));
@@ -656,7 +744,7 @@ BOOL RadTerminalWindowOnCreate(HWND hWnd, LPCREATESTRUCT lpCreateStruct)
const DWORD exstyle = GetWindowExStyle(hWnd);
if (style & WS_VSCROLL)
r.right += GetSystemMetrics(SM_CXVSCROLL);
- CHECK(AdjustWindowRectEx(&r, style, FALSE, exstyle), FALSE);
+ CHECK(AdjustWindowRectEx(&r, style, GetMenu(hWnd) != NULL, exstyle), FALSE);
CHECK(SetWindowPos(hWnd, 0, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_NOMOVE | SWP_NOZORDER), FALSE);
HICON hIconLarge = NULL, hIconSmall = NULL;
@@ -675,6 +763,7 @@ BOOL RadTerminalWindowOnCreate(HWND hWnd, LPCREATESTRUCT lpCreateStruct)
void RadTerminalWindowOnDestroy(HWND hWnd)
{
+ FORWARD_WM_DESTROY(hWnd, MyDefWindowProc);
const RadTerminalData* const data = (RadTerminalData*) GetWindowLongPtr(hWnd, GWLP_USERDATA);
CleanupSubProcess(&data->spd);
@@ -689,7 +778,8 @@ void RadTerminalWindowOnDestroy(HWND hWnd)
delete data;
SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) nullptr);
- PostQuitMessage(0);
+ if (!IsMDIChild(hWnd))
+ PostQuitMessage(0);
}
void RadTerminalWindowOnPaint(HWND hWnd)
@@ -711,7 +801,7 @@ void RadTerminalWindowOnPaint(HWND hWnd)
tsm_age_t age = tsm_screen_draw(data->screen, tsm_screen_draw, (void*) &draw);
Flush(&draw);
- HWND hActive = GetActiveWindow();
+ HWND hActive = MyGetActiveWnd(hWnd);
if (hActive == hWnd)
DrawCursor(hdc, data);
@@ -720,6 +810,7 @@ void RadTerminalWindowOnPaint(HWND hWnd)
void RadTerminalWindowOnKeyDown(HWND hWnd, UINT vk, BOOL fDown, int cRepeat, UINT flags)
{
+ FORWARD_WM_KEYDOWN(hWnd, vk, cRepeat, flags, MyDefWindowProc);
const RadTerminalData* const data = (RadTerminalData*) GetWindowLongPtr(hWnd, GWLP_USERDATA);
BYTE KeyState[256];
GetKeyboardState(KeyState);
@@ -915,19 +1006,20 @@ void RadTerminalWindowOnKeyDown(HWND hWnd, UINT vk, BOOL fDown, int cRepeat, UIN
InvalidateRect(hWnd, nullptr, TRUE);
}
- FORWARD_WM_KEYDOWN(hWnd, vk, cRepeat, flags, DefWindowProc);
+ FORWARD_WM_KEYDOWN(hWnd, vk, cRepeat, flags, MyDefWindowProc);
}
int RadTerminalWindowOnMouseActivate(HWND hWnd, HWND hwndTopLevel, UINT codeHitTest, UINT msg)
{
- int result = FORWARD_WM_MOUSEACTIVATE(hWnd, hwndTopLevel, codeHitTest, msg, DefWindowProc);
- if (result == MA_ACTIVATE)
+ int result = FORWARD_WM_MOUSEACTIVATE(hWnd, hwndTopLevel, codeHitTest, msg, MyDefWindowProc);
+ if (result == MA_ACTIVATE && codeHitTest == HTCLIENT)
return MA_ACTIVATEANDEAT;
return result;
}
void RadTerminalWindowOnMouseMove(HWND hWnd, int x, int y, UINT keyFlags)
{
+ FORWARD_WM_MOUSEMOVE(hWnd, x, y, keyFlags, MyDefWindowProc);
const RadTerminalData* const data = (RadTerminalData*) GetWindowLongPtr(hWnd, GWLP_USERDATA);
if (GetCapture() == hWnd)
{
@@ -939,8 +1031,9 @@ void RadTerminalWindowOnMouseMove(HWND hWnd, int x, int y, UINT keyFlags)
void RadTerminalWindowOnLButtonDown(HWND hWnd, BOOL fDoubleClick, int x, int y, UINT keyFlags)
{
+ FORWARD_WM_LBUTTONDOWN(hWnd, fDoubleClick, x, y, keyFlags, MyDefWindowProc);
const RadTerminalData* const data = (RadTerminalData*) GetWindowLongPtr(hWnd, GWLP_USERDATA);
- if (GetActiveWindow() == hWnd)
+ if (MyGetActiveWnd(hWnd) == hWnd)
{
// TODO Handle fDoubleClick to select word
SetCapture(hWnd);
@@ -952,6 +1045,7 @@ void RadTerminalWindowOnLButtonDown(HWND hWnd, BOOL fDoubleClick, int x, int y,
void RadTerminalWindowOnLButtonUp(HWND hWnd, int x, int y, UINT keyFlags)
{
+ FORWARD_WM_LBUTTONUP(hWnd, x, y, keyFlags, MyDefWindowProc);
const RadTerminalData* const data = (RadTerminalData*) GetWindowLongPtr(hWnd, GWLP_USERDATA);
if (GetCapture() == hWnd)
ReleaseCapture();
@@ -959,6 +1053,7 @@ void RadTerminalWindowOnLButtonUp(HWND hWnd, int x, int y, UINT keyFlags)
void RadTerminalWindowOnRButtonDown(HWND hWnd, BOOL fDoubleClick, int x, int y, UINT keyFlags)
{
+ FORWARD_WM_RBUTTONDOWN(hWnd, fDoubleClick, x, y, keyFlags, MyDefWindowProc);
if (ActionCopyToClipboard(hWnd) < 0)
ActionPasteFromClipboard(hWnd);
}
@@ -980,7 +1075,7 @@ void RadTerminalWindowOnTimer(HWND hWnd, UINT id)
case 2:
{
- HWND hActive = GetActiveWindow();
+ HWND hActive = MyGetActiveWnd(hWnd);
if (hActive == hWnd)
{
HDC hdc = GetDC(hWnd);
@@ -1004,14 +1099,17 @@ void RadTerminalWindowOnSize(HWND hWnd, UINT state, int cx, int cy)
FixScrollbar(hWnd);
}
+ FORWARD_WM_SIZE(hWnd, state, cx, cy, MyDefWindowProc);
}
void RadTerminalWindowOnSizing(HWND hWnd, UINT edge, LPRECT prRect)
{
+ FORWARD_WM_SIZING(hWnd, edge, prRect, MyDefWindowProc);
const RadTerminalData* const data = (RadTerminalData*) GetWindowLongPtr(hWnd, GWLP_USERDATA);
const DWORD style = GetWindowStyle(hWnd);
const DWORD exstyle = GetWindowExStyle(hWnd);
- CHECK_ONLY(UnadjustWindowRectEx(prRect, style, FALSE, exstyle));
+ const BOOL fMenu = GetMenu(hWnd) != NULL;
+ CHECK_ONLY(UnadjustWindowRectEx(prRect, style, fMenu, exstyle));
if (style & WS_VSCROLL)
prRect->right -= GetSystemMetrics(SM_CXVSCROLL);
SIZE sz = GetCellSize(&data->draw_info);
@@ -1041,18 +1139,13 @@ void RadTerminalWindowOnSizing(HWND hWnd, UINT edge, LPRECT prRect)
if (style & WS_VSCROLL)
prRect->right += GetSystemMetrics(SM_CXVSCROLL);
- CHECK_ONLY(AdjustWindowRectEx(prRect, style, FALSE, exstyle));
+ CHECK_ONLY(AdjustWindowRectEx(prRect, style, fMenu, exstyle));
//prRect->right += 100;
}
-void RadTerminalWindowOnActivate(HWND hWnd, UINT state, HWND hwndActDeact, BOOL fMinimized)
-{
- if (state == WA_INACTIVE)
- InvalidateRect(hWnd, nullptr, TRUE);
-}
-
void RadTerminalWindowOnVScroll(HWND hWnd, HWND hWndCtl, UINT code, int pos)
{
+ FORWARD_WM_VSCROLL(hWnd, hWndCtl, code, pos, MyDefWindowProc);
const RadTerminalData* const data = (RadTerminalData*) GetWindowLongPtr(hWnd, GWLP_USERDATA);
const int op = GetScrollPos(hWnd, SB_VERT);
int d = 0;
@@ -1109,12 +1202,18 @@ void RadTerminalWindowOnDropFiles(HWND hWnd, HDROP hDrop)
DragFinish(hDrop);
}
-/* void Cls_OnSizing(HWND hwnd, UINT edge, LPRECT prRect) */
-#define HANDLE_WM_SIZING(hwnd, wParam, lParam, fn) \
- ((fn)((hwnd), (UINT)(wParam), (LPRECT)lParam), TRUE)
+void RadTerminalWindowOnCommand(HWND hWnd, int id, HWND hWndCtl, UINT codeNotify)
+{
+ switch (id)
+ {
+ case ID_FILE_CLOSE: PostMessage(hWnd, WM_CLOSE, 0, 0); break;
+ default: FORWARD_WM_COMMAND(hWnd, id, hWndCtl, codeNotify, MyDefWindowProc); break;
+ }
+}
LRESULT CALLBACK RadTerminalWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
+ //return MyDefWindowProc(hWnd, uMsg, wParam, lParam);
switch (uMsg)
{
HANDLE_MSG(hWnd, WM_CREATE, RadTerminalWindowOnCreate);
@@ -1129,21 +1228,20 @@ LRESULT CALLBACK RadTerminalWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
HANDLE_MSG(hWnd, WM_TIMER, RadTerminalWindowOnTimer);
HANDLE_MSG(hWnd, WM_SIZE, RadTerminalWindowOnSize);
HANDLE_MSG(hWnd, WM_SIZING, RadTerminalWindowOnSizing);
- HANDLE_MSG(hWnd, WM_ACTIVATE, RadTerminalWindowOnActivate);
HANDLE_MSG(hWnd, WM_VSCROLL, RadTerminalWindowOnVScroll);
HANDLE_MSG(hWnd, WM_DROPFILES, RadTerminalWindowOnDropFiles);
+ HANDLE_MSG(hWnd, WM_COMMAND, RadTerminalWindowOnCommand);
case WM_WATCH:
{
const RadTerminalData* const data = (RadTerminalData*) GetWindowLongPtr(hWnd, GWLP_USERDATA);
HANDLE h = (HANDLE) wParam;
if (h == data->spd.pi.hProcess)
{
- DestroyWindow(hWnd);
+ PostMessage(hWnd, WM_CLOSE, 0, 0);
}
return 0;
}
break;
- //HANDLE_MSG(hWnd, WM_CHAR, RadTerminalWindowOnChar);
- default: return DefWindowProc(hWnd, uMsg, wParam, lParam);
+ default: return MyDefWindowProc(hWnd, uMsg, wParam, lParam);
}
}
diff --git a/RadTerminal.rc b/RadTerminal.rc
new file mode 100644
index 0000000..5e289cf
--- /dev/null
+++ b/RadTerminal.rc
Binary files differ
diff --git a/RadTerminal.vcxproj b/RadTerminal.vcxproj
index 45ec2d8..f517f98 100644
--- a/RadTerminal.vcxproj
+++ b/RadTerminal.vcxproj
@@ -96,6 +96,7 @@
<ItemGroup>
<ClCompile Include="ProcessUtils.cpp" />
<ClCompile Include="RadTerminal.cpp" />
+ <ClCompile Include="RadTerminalFrame.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="tsm.vcxproj">
@@ -104,8 +105,12 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="ProcessUtils.h" />
+ <ClInclude Include="resource.h" />
<ClInclude Include="WinUtils.h" />
</ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="RadTerminal.rc" />
+ </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
diff --git a/RadTerminalFrame.cpp b/RadTerminalFrame.cpp
new file mode 100644
index 0000000..e605da8
--- /dev/null
+++ b/RadTerminalFrame.cpp
@@ -0,0 +1,116 @@
+#include <windows.h>
+#include <windowsx.h>
+#include "WinUtils.h"
+#include "resource.h"
+
+#define PROJ_NAME TEXT("RadTerminal")
+
+HWND ActionNewWindow(HWND hWnd, bool bParseCmdLine);
+LRESULT CALLBACK RadTerminalMDIFrameProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+HWND CreateRadTerminalFrame(HINSTANCE hInstance, int nCmdShow)
+{
+ WNDCLASS wcMDIFrame = {};
+
+ wcMDIFrame.lpfnWndProc = RadTerminalMDIFrameProc;
+ wcMDIFrame.hIcon = LoadIcon(NULL, IDI_APPLICATION);
+ wcMDIFrame.hCursor = LoadCursor(NULL, IDC_ARROW);
+ //wcMDIFrame.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
+ wcMDIFrame.hInstance = hInstance;
+ wcMDIFrame.lpszClassName = TEXT("MDIRadTerminal");
+
+ ATOM atomFrame = RegisterClass(&wcMDIFrame);
+ if (atomFrame == NULL)
+ return NULL;
+
+ HWND hFrame = CreateWindow(
+ MAKEINTATOM(atomFrame),
+ PROJ_NAME,
+ WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
+ NULL, // Parent window
+ LoadMenu(hInstance, MAKEINTRESOURCE(IDR_MENU1)), // Menu
+ hInstance,
+ nullptr
+ );
+ if (hFrame == NULL)
+ return NULL;
+
+ ShowWindow(hFrame, nCmdShow);
+
+ return hFrame;
+}
+
+inline LRESULT MyDefFrameWindowProc(_In_ HWND hWnd, _In_ UINT Msg, _In_ WPARAM wParam, _In_ LPARAM lParam)
+{
+ return DefFrameProc(hWnd, GetMDIClient(hWnd), Msg, wParam, lParam);
+}
+
+BOOL RadTerminalFrameOnCreate(HWND hWnd, LPCREATESTRUCT lpCreateStruct)
+{
+ FORWARD_WM_CREATE(hWnd, lpCreateStruct, MyDefFrameWindowProc);
+ HINSTANCE hInst = GetWindowInstance(hWnd);
+
+ CLIENTCREATESTRUCT ccs = {};
+ HMENU hMenu = GetMenu(hWnd);
+ ccs.hWindowMenu = GetSubMenu(hMenu, GetMenuItemCount(hMenu) - 1);
+ ccs.idFirstChild = IDM_WINDOWCHILD;
+
+ HWND hWndMDIClient = CreateWindow(TEXT("MDICLIENT"), (LPCTSTR) NULL,
+ WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL,
+ 0, 0, 0, 0, hWnd, (HMENU) 0, hInst, (LPSTR) &ccs);
+
+ ShowWindow(hWndMDIClient, SW_SHOW);
+
+ return TRUE;
+}
+
+void RadTerminalFrameOnDestroy(HWND hWnd)
+{
+ FORWARD_WM_DESTROY(hWnd, MyDefFrameWindowProc);
+ PostQuitMessage(0);
+}
+
+void RadTerminalFrameOnSizing(HWND hWnd, UINT edge, LPRECT prRect)
+{
+ FORWARD_WM_SIZING(hWnd, edge, prRect, MyDefFrameWindowProc);
+ HWND hWndMDIClient = GetMDIClient(hWnd);
+ BOOL bMaximized = FALSE;
+ HWND hActive = GetMDIActive(hWndMDIClient, &bMaximized);
+ if (hActive != NULL && bMaximized)
+ {
+ FORWARD_WM_SIZING(hActive, edge, prRect, SendMessage);
+ UnadjustWindowRectEx(prRect, GetWindowStyle(hActive), GetMenu(hActive) != NULL, GetWindowExStyle(hActive));
+ AdjustWindowRectEx(prRect, GetWindowStyle(hWnd), GetMenu(hWnd) != NULL, GetWindowExStyle(hWnd));
+ }
+}
+
+void RadTerminalFrameOnCommand(HWND hWnd, int id, HWND hWndCtl, UINT codeNotify)
+{
+ HWND hWndMDIClient = GetMDIClient(hWnd);
+
+ switch (id)
+ {
+ case ID_FILE_NEW: ActionNewWindow(hWnd, false); break;
+ case ID_FILE_EXIT: PostMessage(hWnd, WM_CLOSE, 0, 0); break;
+ case ID_WINDOW_CASCADE: CascadeWindows(hWndMDIClient, 0, nullptr, 0, nullptr); break;
+ case ID_WINDOW_TILEHORIZONTALLY: TileWindows(hWndMDIClient, MDITILE_HORIZONTAL, nullptr, 0, nullptr); break;
+ case ID_WINDOW_TILEVERTICALLY: TileWindows(hWndMDIClient, MDITILE_VERTICAL, nullptr, 0, nullptr); break;
+
+ case ID_FILE_CLOSE: FORWARD_WM_COMMAND(GetMDIActive(hWndMDIClient), id, hWndCtl, codeNotify, SendMessage); break;
+
+ default: FORWARD_WM_COMMAND(hWnd, id, hWndCtl, codeNotify, MyDefFrameWindowProc); break;
+ }
+}
+
+LRESULT CALLBACK RadTerminalMDIFrameProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ HANDLE_MSG(hWnd, WM_CREATE, RadTerminalFrameOnCreate);
+ HANDLE_MSG(hWnd, WM_DESTROY, RadTerminalFrameOnDestroy);
+ HANDLE_MSG(hWnd, WM_SIZING, RadTerminalFrameOnSizing);
+ HANDLE_MSG(hWnd, WM_COMMAND, RadTerminalFrameOnCommand);
+ default: return MyDefFrameWindowProc(hWnd, uMsg, wParam, lParam);
+ }
+}
diff --git a/WinUtils.h b/WinUtils.h
index ff12f68..d020727 100644
--- a/WinUtils.h
+++ b/WinUtils.h
@@ -1,5 +1,18 @@
#pragma once
#include <windows.h>
+#include <string>
+
+#ifdef _UNICODE
+#define tstring wstring
+#else
+#define tstring string
+#endif
+
+/* void Cls_OnSizing(HWND hwnd, UINT edge, LPRECT prRect) */
+#define HANDLE_WM_SIZING(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), (UINT)(wParam), (LPRECT)lParam), TRUE)
+#define FORWARD_WM_SIZING(hwnd, edge, prRect, fn) \
+ (void)(fn)((hwnd), WM_SIZING, (WPARAM)edge, (LPARAM)prRect)
inline BOOL UnadjustWindowRect(
LPRECT prc,
@@ -53,33 +66,33 @@ inline HFONT CreateFont(LPCTSTR pFontFace, int iFontHeight, int cWeight, BOOL bI
DEFAULT_PITCH | FF_DONTCARE, pFontFace);
}
-std::string RegGetString(HKEY hKey, LPCSTR sValue, const std::string& strDef)
+inline std::string RegGetString(HKEY hKey, LPCSTR sValue, const std::string& strDef)
{
CHAR buf[1024];
DWORD len = (ARRAYSIZE(buf) - 1) * sizeof(CHAR);
if (RegGetValueA(hKey, nullptr, sValue, RRF_RT_REG_SZ, nullptr, buf, &len) == ERROR_SUCCESS)
{
- buf[len / sizeof(CHAR)] = _T('\0');
+ buf[len / sizeof(CHAR)] = TEXT('\0');
return buf;
}
else
return strDef;
}
-std::wstring RegGetString(HKEY hKey, LPCWSTR sValue, const std::wstring& strDef)
+inline std::tstring RegGetString(HKEY hKey, LPCWSTR sValue, const std::tstring& strDef)
{
WCHAR buf[1024];
DWORD len = (ARRAYSIZE(buf) - 1) * sizeof(WCHAR);
if (RegGetValueW(hKey, nullptr, sValue, RRF_RT_REG_SZ, nullptr, buf, &len) == ERROR_SUCCESS)
{
- buf[len / sizeof(WCHAR)] = _T('\0');
+ buf[len / sizeof(WCHAR)] = TEXT('\0');
return buf;
}
else
return strDef;
}
-DWORD RegGetDWORD(HKEY hKey, LPCTSTR sValue, DWORD dwDef)
+inline DWORD RegGetDWORD(HKEY hKey, LPCTSTR sValue, DWORD dwDef)
{
DWORD data = 0;
DWORD len = sizeof(data);
@@ -88,3 +101,26 @@ DWORD RegGetDWORD(HKEY hKey, LPCTSTR sValue, DWORD dwDef)
else
return dwDef;
}
+
+inline HWND GetMDIClient(HWND hWnd)
+{
+ return FindWindowEx(hWnd, NULL, TEXT("MDICLIENT"), nullptr);
+}
+
+inline HWND GetMDIActive(HWND hWndMDIClient, BOOL* pbMaximized = nullptr)
+{
+ return (HWND) SendMessage(hWndMDIClient, WM_MDIGETACTIVE, 0, (LPARAM) pbMaximized);
+}
+
+inline bool IsMDIChild(HWND hWnd)
+{
+ return (GetWindowExStyle(hWnd) & WS_EX_MDICHILD) != 0;
+}
+
+inline HWND MyGetActiveWnd(HWND hWnd)
+{
+ HWND hActive = GetActiveWindow();
+ if (hActive != NULL && IsMDIChild(hWnd))
+ hActive = GetMDIActive(GetParent(hWnd));
+ return hActive;
+}
diff --git a/resource.h b/resource.h
new file mode 100644
index 0000000..64624e0
--- /dev/null
+++ b/resource.h
Binary files differ