📄 guiconsole.c
字号:
}
}
VOID FASTCALL
GuiConsoleCreateScrollBar(PCSRSS_CONSOLE Console, PGUI_CONSOLE_DATA GuiData, HWND NewWindow)
{
HMENU hMenu;
HWND hVScrollBar;
HWND hHScrollBar;
SCROLLINFO sInfo;
hMenu = CreatePopupMenu();
if (hMenu == NULL)
{
DPRINT("CreatePopupMenu failed\n");
return;
}
//InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLHERE);
//InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
//InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLTOP);
//InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLBOTTOM);
//InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
//InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLPAGE_UP);
//InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLPAGE_DOWN);
//InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
//InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLUP);
//InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLDOWN);
hVScrollBar = CreateWindowExW(0L,
L"ScrollBar",
(LPWSTR)NULL,
WS_CHILD | WS_VSCROLL,
0,
0,
200,
50,
NewWindow,
NULL, //hMenu,
GetModuleHandleW(NULL),
(LPVOID)GuiData);
if (hVScrollBar)
{
/* set scrollbar sizes */
sInfo.cbSize = sizeof(SCROLLINFO);
sInfo.fMask = SIF_RANGE | SIF_POS;
sInfo.nMin = 0;
sInfo.nMax = Console->ActiveBuffer->MaxY;
sInfo.nPos = 0;
SetScrollInfo(hVScrollBar, SB_CTL, &sInfo, TRUE);
ShowScrollBar(NewWindow, SB_CTL, TRUE);
GuiData->hVScrollBar = hVScrollBar;
}
if (Console->ActiveBuffer->MaxX > Console->Size.X)
{
hHScrollBar = CreateWindowExW(0L,
L"ScrollBar",
(LPWSTR)NULL,
WS_CHILD | WS_HSCROLL,
0,
0,
200,
CW_USEDEFAULT,
NewWindow,
hMenu,
GetModuleHandleW(NULL),
(LPVOID)GuiData);
if (hHScrollBar)
{
sInfo.nMax = Console->ActiveBuffer->MaxX;
SetScrollInfo(hHScrollBar, SB_CTL, &sInfo, TRUE);
GuiData->hHScrollBar = hHScrollBar;
}
}
}
static VOID FASTCALL
GuiApplyUserSettings(PCSRSS_CONSOLE Console, PGUI_CONSOLE_DATA GuiData, PConsoleInfo pConInfo)
{
DWORD windx, windy;
RECT rect;
/* apply text / background color */
GuiData->ScreenText = pConInfo->ScreenText;
GuiData->ScreenBackground = pConInfo->ScreenBackground;
/* apply cursor size */
Console->ActiveBuffer->CursorInfo.dwSize = max(min(pConInfo->CursorSize, 1), 100);
windx = LOWORD(pConInfo->ScreenBuffer);
windy = HIWORD(pConInfo->ScreenBuffer);
if (windx != Console->ActiveBuffer->MaxX || windy != Console->ActiveBuffer->MaxY)
{
//
// TODO
// resize screen buffer
// Console->ActiveBuffer->MaxX = windx;
// Console->ActiveBuffer->MaxY = windy;
}
windx = LOWORD(pConInfo->WindowSize);
windy = HIWORD(pConInfo->WindowSize);
if (windx != Console->Size.X || windy != Console->Size.Y)
{
/* resize window */
Console->Size.X = windx;
Console->Size.Y = windy;
GetWindowRect(pConInfo->hConsoleWindow, &rect);
rect.right = rect.left + Console->Size.X * GuiData->CharWidth + 2 * GetSystemMetrics(SM_CXFIXEDFRAME);
rect.bottom = rect.top + Console->Size.Y * GuiData->CharHeight + 2 * GetSystemMetrics(SM_CYFIXEDFRAME) + GetSystemMetrics(SM_CYCAPTION);
MoveWindow(pConInfo->hConsoleWindow, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, FALSE);
if (Console->Size.X < Console->ActiveBuffer->MaxX)
{
/* show scrollbar when window becomes smaller than active screen buffer */
//ShowScrollBar(GuiData->hHScrollBar, SB_CTL, TRUE);
}
else
{
/* hide scrollbar */
//ShowScrollBar(GuiData->hHScrollBar, SB_CTL, FALSE);
}
}
/* repaint window */
InvalidateRect(pConInfo->hConsoleWindow, NULL, TRUE);
}
static LRESULT CALLBACK
GuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
LRESULT Result = 0;
PGUI_CONSOLE_DATA GuiData = NULL;
PCSRSS_CONSOLE Console = NULL;
GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
switch(msg)
{
case WM_NCCREATE:
Result = (LRESULT) GuiConsoleHandleNcCreate(hWnd, (CREATESTRUCTW *) lParam);
break;
case WM_PAINT:
GuiConsoleHandlePaint(hWnd, (HDC)wParam);
break;
case WM_KEYDOWN:
case WM_KEYUP:
case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
case WM_CHAR:
GuiConsoleHandleKey(hWnd, msg, wParam, lParam);
break;
case WM_TIMER:
GuiConsoleHandleTimer(hWnd);
break;
case WM_CLOSE:
GuiConsoleHandleClose(hWnd);
break;
case WM_NCDESTROY:
GuiConsoleHandleNcDestroy(hWnd);
break;
case WM_LBUTTONDOWN:
GuiConsoleLeftMouseDown(hWnd, lParam);
break;
case WM_LBUTTONUP:
GuiConsoleLeftMouseUp(hWnd, lParam);
break;
case WM_RBUTTONDOWN:
GuiConsoleRightMouseDown(hWnd);
break;
case WM_MOUSEMOVE:
GuiConsoleMouseMove(hWnd, wParam, lParam);
break;
case WM_SYSCOMMAND:
Result = GuiConsoleHandleSysMenuCommand(hWnd, wParam, lParam, GuiData);
break;
case WM_SIZE:
GuiConsoleResize(hWnd, wParam, lParam);
break;
case PM_APPLY_CONSOLE_INFO:
GuiApplyUserSettings(Console, GuiData, (PConsoleInfo)wParam);
if (lParam)
{
GuiConsoleWriteUserSettings(Console, GuiData);
}
break;
default:
Result = DefWindowProcW(hWnd, msg, wParam, lParam);
break;
}
return Result;
}
static LRESULT CALLBACK
GuiConsoleNotifyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
HWND NewWindow;
LONG WindowCount;
MSG Msg;
PWCHAR Buffer, Title;
PCSRSS_CONSOLE Console = (PCSRSS_CONSOLE) lParam;
switch(msg)
{
case WM_CREATE:
SetWindowLongW(hWnd, GWL_USERDATA, 0);
return 0;
case PM_CREATE_CONSOLE:
Buffer = HeapAlloc(Win32CsrApiHeap, 0,
Console->Title.Length + sizeof(WCHAR));
if (NULL != Buffer)
{
memcpy(Buffer, Console->Title.Buffer, Console->Title.Length);
Buffer[Console->Title.Length / sizeof(WCHAR)] = L'\0';
Title = Buffer;
}
else
{
Title = L"";
}
NewWindow = CreateWindowW(L"ConsoleWindowClass",
Title,
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, //WS_OVERLAPPEDWINDOW
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
(HINSTANCE) GetModuleHandleW(NULL),
(PVOID) Console);
if (NULL != Buffer)
{
HeapFree(Win32CsrApiHeap, 0, Buffer);
}
if (NULL != NewWindow)
{
// scrollbar support
//GuiConsoleCreateScrollBar(Console, (PGUI_CONSOLE_DATA)Console->PrivateData, NewWindow);
SetWindowLongW(hWnd, GWL_USERDATA, GetWindowLongW(hWnd, GWL_USERDATA) + 1);
ShowWindow(NewWindow, SW_SHOW);
}
return (LRESULT) NewWindow;
case PM_DESTROY_CONSOLE:
/* Window creation is done using a PostMessage(), so it's possible that the
* window that we want to destroy doesn't exist yet. So first empty the message
* queue */
while(PeekMessageW(&Msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&Msg);
DispatchMessageW(&Msg);
}
DestroyWindow(Console->hWindow);
Console->hWindow = NULL;
WindowCount = GetWindowLongW(hWnd, GWL_USERDATA);
WindowCount--;
SetWindowLongW(hWnd, GWL_USERDATA, WindowCount);
if (0 == WindowCount)
{
NotifyWnd = NULL;
DestroyWindow(hWnd);
PrivateCsrssManualGuiCheck(-1);
PostQuitMessage(0);
}
return 0;
default:
return DefWindowProcW(hWnd, msg, wParam, lParam);
}
}
static DWORD STDCALL
GuiConsoleGuiThread(PVOID Data)
{
MSG msg;
PHANDLE GraphicsStartupEvent = (PHANDLE) Data;
NotifyWnd = CreateWindowW(L"Win32CsrCreateNotify",
L"",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
(HINSTANCE) GetModuleHandleW(NULL),
NULL);
if (NULL == NotifyWnd)
{
PrivateCsrssManualGuiCheck(-1);
SetEvent(*GraphicsStartupEvent);
return 1;
}
SetEvent(*GraphicsStartupEvent);
while(GetMessageW(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return 1;
}
static BOOL FASTCALL
GuiInit(VOID)
{
WNDCLASSEXW wc;
if (NULL == NotifyWnd)
{
PrivateCsrssManualGuiCheck(+1);
}
wc.cbSize = sizeof(WNDCLASSEXW);
wc.lpszClassName = L"Win32CsrCreateNotify";
wc.lpfnWndProc = GuiConsoleNotifyWndProc;
wc.style = 0;
wc.hInstance = (HINSTANCE) GetModuleHandleW(NULL);
wc.hIcon = NULL;
wc.hCursor = NULL;
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hIconSm = NULL;
if (RegisterClassExW(&wc) == 0)
{
DPRINT1("Failed to register notify wndproc\n");
return FALSE;
}
wc.cbSize = sizeof(WNDCLASSEXW);
wc.lpszClassName = L"ConsoleWindowClass";
wc.lpfnWndProc = GuiConsoleWndProc;
wc.style = 0;
wc.hInstance = (HINSTANCE) GetModuleHandleW(NULL);
wc.hIcon = LoadIconW(Win32CsrDllHandle, MAKEINTRESOURCEW(1));
wc.hCursor = LoadCursorW(NULL, (LPCWSTR) IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hIconSm = LoadImageW(Win32CsrDllHandle, MAKEINTRESOURCEW(1), IMAGE_ICON,
GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON),
LR_SHARED);
if (RegisterClassExW(&wc) == 0)
{
DPRINT1("Failed to register console wndproc\n");
return FALSE;
}
return TRUE;
}
static VOID STDCALL
GuiInitScreenBuffer(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buffer)
{
Buffer->DefaultAttrib = DEFAULT_ATTRIB;
}
static BOOL STDCALL
GuiChangeTitle(PCSRSS_CONSOLE Console)
{
PWCHAR Buffer, Title;
Buffer = HeapAlloc(Win32CsrApiHeap, 0,
Console->Title.Length + sizeof(WCHAR));
if (NULL != Buffer)
{
memcpy(Buffer, Console->Title.Buffer, Console->Title.Length);
Buffer[Console->Title.Length / sizeof(WCHAR)] = L'\0';
Title = Buffer;
}
else
{
Title = L"";
}
SendMessageW(Console->hWindow, WM_SETTEXT, 0, (LPARAM) Title);
if (NULL != Buffer)
{
HeapFree(Win32CsrApiHeap, 0, Buffer);
}
return TRUE;
}
static BOOL STDCALL
GuiChangeIcon(PCSRSS_CONSOLE Console)
{
SendMessageW(Console->hWindow, WM_SETICON, ICON_BIG, (LPARAM)Console->hWindowIcon);
SendMessageW(Console->hWindow, WM_SETICON, ICON_SMALL, (LPARAM)Console->hWindowIcon);
return TRUE;
}
static VOID STDCALL
GuiCleanupConsole(PCSRSS_CONSOLE Console)
{
SendMessageW(NotifyWnd, PM_DESTROY_CONSOLE, 0, (LPARAM) Console);
}
static CSRSS_CONSOLE_VTBL GuiVtbl =
{
GuiInitScreenBuffer,
GuiWriteStream,
GuiDrawRegion,
GuiSetCursorInfo,
GuiSetScreenInfo,
GuiChangeTitle,
GuiCleanupConsole,
GuiChangeIcon
};
NTSTATUS FASTCALL
GuiInitConsole(PCSRSS_CONSOLE Console)
{
HANDLE GraphicsStartupEvent;
HANDLE ThreadHandle;
PGUI_CONSOLE_DATA GuiData;
if (! ConsInitialized)
{
ConsInitialized = TRUE;
if (! GuiInit())
{
ConsInitialized = FALSE;
return STATUS_UNSUCCESSFUL;
}
}
Console->Vtbl = &GuiVtbl;
if (NULL == NotifyWnd)
{
GraphicsStartupEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
if (NULL == GraphicsStartupEvent)
{
return STATUS_UNSUCCESSFUL;
}
ThreadHandle = CreateThread(NULL,
0,
GuiConsoleGuiThread,
(PVOID) &GraphicsStartupEvent,
0,
NULL);
if (NULL == ThreadHandle)
{
NtClose(GraphicsStartupEvent);
DPRINT1("Win32Csr: Failed to create graphics console thread. Expect problems\n");
return STATUS_UNSUCCESSFUL;
}
SetThreadPriority(ThreadHandle, THREAD_PRIORITY_HIGHEST);
CloseHandle(ThreadHandle);
WaitForSingleObject(GraphicsStartupEvent, INFINITE);
CloseHandle(GraphicsStartupEvent);
if (NULL == NotifyWnd)
{
DPRINT1("Win32Csr: Failed to create notification window.\n");
return STATUS_UNSUCCESSFUL;
}
}
GuiData = HeapAlloc(Win32CsrApiHeap, HEAP_ZERO_MEMORY,
sizeof(GUI_CONSOLE_DATA));
if (!GuiData)
{
DPRINT1("Win32Csr: Failed to create GUI_CONSOLE_DATA\n");
return STATUS_UNSUCCESSFUL;
}
Console->PrivateData = (PVOID) GuiData;
/*
* we need to wait untill the GUI has been fully initialized
* to retrieve custom settings i.e. WindowSize etc..
* Ideally we could use SendNotifyMessage for this but its not
* yet implemented.
*
*/
GuiData->hGuiInitEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
/* create console */
PostMessageW(NotifyWnd, PM_CREATE_CONSOLE, 0, (LPARAM) Console);
/* wait untill initialization has finished */
WaitForSingleObject(GuiData->hGuiInitEvent, INFINITE);
DPRINT1("received event Console %p GuiData %p X %d Y %d\n", Console, Console->PrivateData, Console->Size.X, Console->Size.Y);
CloseHandle(GuiData->hGuiInitEvent);
GuiData->hGuiInitEvent = NULL;
return STATUS_SUCCESS;
}
/* EOF */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -