📄 form1.cpp
字号:
#include <monapi/syscall.h>
#include <monapi/messages.h>
#include <gui/System/Mona/Forms/Application.h>
#include <gui/System/Mona/Forms/Button.h>
#include <gui/System/Mona/Forms/Form.h>
#include <gui/System/Mona/Forms/ControlPaint.h>
#define FONT_WIDTH 6
#define FONT_HEIGHT 12
#define SHELL_WIDTH 80
#define SHELL_HEIGHT 25
using namespace System;
using namespace System::Drawing;
using namespace System::Mona::Forms;
extern _P<MonAPI::Screen> GetDefaultScreen();
class Terminal : public Control
{
public:
Terminal() : x(0), y(0)
{
this->set_BackColor(Color::get_White());
this->offset = Point(2, 2);
}
virtual ~Terminal() {}
virtual void OnPaint()
{
_P<Graphics> g = Graphics::FromImage(this->buffer);
ControlPaint::DrawSunken(g, 0, 0, this->get_Width(), this->get_Height());
g->Dispose();
}
void Output(String s)
{
_P<Graphics> g = this->CreateGraphics();
Size r = this->get_ClientSize();
wchar prev = 0;
FOREACH (wchar, ch, s)
{
if (ch == '\r' || ch == '\n')
{
if (prev == '\r' && ch == '\n') continue;
x = 0;
if (y <= r.Height - FONT_HEIGHT * 2)
{
y += FONT_HEIGHT;
}
else
{
Color* img = this->buffer->get();
for (int yy = 0; yy < r.Height - FONT_HEIGHT; yy++)
{
int p = (yy + this->offset.Y) * this->get_Width() + this->offset.X;
int d = this->get_Width() * FONT_HEIGHT;
for (int xx = 0; xx < r.Width; xx++, p++)
{
img[p] = img[p + d];
}
}
x = 0;
g->FillRectangle(this->get_BackColor(), 0, y, r.Width, r.Height - y);
}
}
else
{
_A<wchar> buf(1);
buf[0] = ch;
int sw = g->MeasureString(buf, Control::get_DefaultFont()).Width;
int sw2 = ch < 256 ? FONT_WIDTH : FONT_WIDTH * 2;
g->DrawString(buf, Control::get_DefaultFont(), Color::get_Black(), x + (sw2 - sw) / 2, y);
x += sw2;
}
prev = ch;
}
END_FOREACH
g->Dispose();
}
private:
int x, y;
};
static dword my_tid, stdout_tid;
static _P<Terminal> terminal;
static void StdoutMessageLoop()
{
MonAPI::Message::send(my_tid, MSG_SERVER_START_OK);
for (MessageInfo msg;;)
{
if (MonAPI::Message::receive(&msg) != 0) continue;
switch (msg.header)
{
case MSG_PROCESS_STDOUT_DATA:
case MSG_STDOUT: /* higepon exp */
{
msg.str[127] = '\0';
terminal->Output(msg.str);
terminal->Refresh();
MonAPI::Message::reply(&msg);
break;
}
}
}
}
static void InitThread()
{
my_tid = syscall_get_tid();
dword id = syscall_mthread_create((dword)StdoutMessageLoop);
syscall_mthread_join(id);
MessageInfo msg, src;
src.header = MSG_SERVER_START_OK;
MonAPI::Message::receive(&msg, &src, MonAPI::Message::equalsHeader);
stdout_tid = msg.from;
}
class Form1 : public Form
{
public:
Form1()
{
this->InitializeComponent();
_P<MonAPI::Screen> scr = GetDefaultScreen();
this->set_Location(Point((scr->getWidth() - this->get_Width()) / 2, (scr->getHeight() - this->get_Height()) / 2));
terminal = new Terminal();
terminal->set_Bounds(Rectangle(Point::get_Empty(), this->get_ClientSize()));
this->get_Controls()->Add(terminal.get());
}
private:
void InitializeComponent()
{
this->set_ClientSize(Size(SHELL_WIDTH * FONT_WIDTH + 4, SHELL_HEIGHT * FONT_HEIGHT + 4));
this->set_Text("GUI Shell");
this->set_Opacity(0.8);
}
public:
static void Main(_A<String> args)
{
_P<Form> f = new Form1();
InitThread();
dword tid = monapi_get_server_thread_id(ID_PROCESS_SERVER);
if (tid != THREAD_UNKNOWN)
{
MonAPI::Message::sendReceive(NULL, tid + 1, MSG_PROCESS_GRAB_STDOUT, stdout_tid);
}
Application::Run(f);
if (tid != THREAD_UNKNOWN)
{
MonAPI::Message::sendReceive(NULL, tid + 1, MSG_PROCESS_UNGRAB_STDOUT, stdout_tid);
}
syscall_kill_thread(stdout_tid);
}
};
SET_MAIN_CLASS(Form1)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -