GUI: Windows console improvements, hide the border as much as possible when docked, unlimited size, retain colors and cursor position on resize etc

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4103 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
John Peterson 2009-08-30 08:22:05 +00:00
parent 135a0818eb
commit 81483f928c
6 changed files with 225 additions and 54 deletions

View File

@ -57,23 +57,12 @@ void ConsoleListener::Open(int Width, int Height, const char *Title)
#ifdef _WIN32
// Open the console window and create the window handle for GetStdHandle()
AllocConsole();
// Save the window handle that AllocConsole() created
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
// Set the console window title
SetConsoleTitle(Title);
// Set the total letter space to MAX_BYTES
int LWidth = Width / 8;
int LBufHeight = floor((float)(MAX_BYTES / (LWidth + 1)));
COORD co = {LWidth, LBufHeight};
SetConsoleScreenBufferSize(hConsole, co);
/* Set the window size in number of letters. The height is hard coded here
because it can be changed with MoveWindow() later */
SMALL_RECT coo = {0,0, (LWidth - 1), 50}; // Top, left, right, bottom
SetConsoleWindowInfo(hConsole, TRUE, &coo);
// Set letter space
LetterSpace(80, 4000);
#endif
}
@ -104,68 +93,175 @@ bool ConsoleListener::IsOpen()
////////////////////////////////////////////////////////////////////////////////////////////////////////
// Size
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
/*
Short documentation:
LetterSpace: SetConsoleScreenBufferSize and SetConsoleWindowInfo are dependent on each other, that's the
reason for the additional checks.
*/
void ConsoleListener::BufferWidthHeight(int BufferWidth, int BufferHeight, int ScreenWidth, int ScreenHeight, bool BufferFirst)
{
#ifdef _WIN32
bool SB, SW;
if (BufferFirst)
{
// Change screen buffer size
COORD Co = {BufferWidth, BufferHeight};
SB = SetConsoleScreenBufferSize(hConsole, Co);
// Change the screen buffer window size
SMALL_RECT coo = {0,0,ScreenWidth, ScreenHeight}; // top, left, right, bottom
SW = SetConsoleWindowInfo(hConsole, TRUE, &coo);
}
else
{
// Change the screen buffer window size
SMALL_RECT coo = {0,0, ScreenWidth, ScreenHeight}; // top, left, right, bottom
SW = SetConsoleWindowInfo(hConsole, TRUE, &coo);
// Change screen buffer size
COORD Co = {BufferWidth, BufferHeight};
SB = SetConsoleScreenBufferSize(hConsole, Co);
}
#endif
}
void ConsoleListener::LetterSpace(int Width, int Height)
{
#ifdef _WIN32
// Get console info
CONSOLE_SCREEN_BUFFER_INFO ConInfo;
GetConsoleScreenBufferInfo(hConsole, &ConInfo);
// Change the screen buffer window size
SMALL_RECT coo = {0,0, Width, Height}; // top, left, right, bottom
bool SW = SetConsoleWindowInfo(hConsole, TRUE, &coo);
//
int OldBufferWidth = ConInfo.dwSize.X;
int OldBufferHeight = ConInfo.dwSize.Y;
int OldScreenWidth = (ConInfo.srWindow.Right - ConInfo.srWindow.Left);
int OldScreenHeight = (ConInfo.srWindow.Bottom - ConInfo.srWindow.Top);
//
int NewBufferWidth = Width;
int NewBufferHeight = Height;
int NewScreenWidth = NewBufferWidth - 1;
int NewScreenHeight = OldScreenHeight;
// Change screen buffer to the screen buffer window size
COORD Co = {Width + 1, Height + 1};
bool SB = SetConsoleScreenBufferSize(hConsole, Co);
// Width
BufferWidthHeight(NewBufferWidth, OldBufferHeight, NewScreenWidth, OldScreenHeight, (NewBufferWidth > OldScreenWidth-1));
// Height
BufferWidthHeight(NewBufferWidth, NewBufferHeight, NewScreenWidth, NewScreenHeight, (NewBufferHeight > OldScreenHeight-1));
// Resize the window too
MoveWindow(GetConsoleWindow(), 200,200, (Width*8 + 50),(Height*12 + 50), true);
// Logging
//printf("LetterSpace(): L:%i T:%i Iconic:%i\n", ConsoleLeft, ConsoleTop, ConsoleIconic);
//MoveWindow(GetConsoleWindow(), 200,200, (Width*8 + 50),(NewScreenHeight*12 + 200), true);
#endif
}
#ifdef _WIN32
COORD ConsoleListener::GetCoordinates(int BytesRead, int BufferWidth)
{
COORD Ret = {0, 0};
// Full rows
int Step = floor((float)BytesRead / (float)BufferWidth);
Ret.Y += Step;
// Partial row
Ret.X = BytesRead - (BufferWidth * Step);
return Ret;
}
#endif
void ConsoleListener::PixelSpace(int Left, int Top, int Width, int Height, bool Resize)
{
#ifdef _WIN32
// Check size
if (Width < 8 || Height < 12) return;
bool DBef = true;
bool DAft = true;
std::string SLog = "";
HWND hWnd = GetConsoleWindow();
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
// Get console info
CONSOLE_SCREEN_BUFFER_INFO ConInfo;
GetConsoleScreenBufferInfo(hConsole, &ConInfo);
// Letter space
int LWidth = floor((float)(Width / 8));
int LHeight = floor((float)(Height / 12));
int LBufHeight = floor((float)(MAX_BYTES / (LWidth + 1)));
DWORD BufferSize = ConInfo.dwSize.X * ConInfo.dwSize.Y;
// Check size
DWORD dwConSize = ConInfo.dwSize.X * ConInfo.dwSize.Y;
if (dwConSize > MAX_BYTES) return;
// Read the current text
char Str[MAX_BYTES];
// ---------------------------------------------------------------------
// Save the current text
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
DWORD cCharsRead = 0;
COORD coordScreen = { 0, 0 };
ReadConsoleOutputCharacter(hConsole, Str, dwConSize, coordScreen, &cCharsRead);
// Change the screen buffer window size
SMALL_RECT coo = {0,0, LWidth, LHeight}; // top, left, right, bottom
bool bW = SetConsoleWindowInfo(hConsole, TRUE, &coo);
// Change screen buffer to the screen buffer window size
COORD Co = {LWidth + 1, LBufHeight};
bool bB = SetConsoleScreenBufferSize(hConsole, Co);
std::vector<char*> Str;
std::vector<WORD*> Attr;
// ReadConsoleOutputAttribute seems to have a limit at this level
const int MAX_BYTES = 1024 * 16;
int ReadBufferSize = MAX_BYTES - 32;
DWORD cAttrRead = ReadBufferSize;
int BytesRead = 0;
int i = 0;
int LastAttrRead = 0;
while(BytesRead < BufferSize)
{
Str.push_back(new char[MAX_BYTES]);
if (!ReadConsoleOutputCharacter(hConsole, Str[i], ReadBufferSize, coordScreen, &cCharsRead))
SLog += StringFromFormat("WriteConsoleOutputCharacter error");
Attr.push_back(new WORD[MAX_BYTES]);
if (!ReadConsoleOutputAttribute(hConsole, Attr[i], ReadBufferSize, coordScreen, &cAttrRead))
SLog += StringFromFormat("WriteConsoleOutputAttribute error");
// Redraw the text
// Break on error
if (cAttrRead == 0) break;
BytesRead += cAttrRead;
i++;
coordScreen = GetCoordinates(BytesRead, ConInfo.dwSize.X);
LastAttrRead = cAttrRead;
}
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// Modify the buffer proportions
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// Letter space
int LWidth = floor((float)Width / 8.0) - 1.0;
int LHeight = floor((float)Height / 12.0) - 1.0;
int LBufWidth = LWidth + 1;
int LBufHeight = floor((float)BufferSize / (float)LBufWidth);
// Change screen buffer size
LetterSpace(LBufWidth, LBufHeight);
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// Redraw the text
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
ClearScreen(true);
coordScreen.Y = 0;
coordScreen.X = 0;
DWORD cCharsWritten = 0;
WriteConsoleOutputCharacter(hConsole, Str, cCharsRead, coordScreen, &cCharsWritten);
int BytesWritten = 0;
DWORD cAttrWritten = 0;
for (int i = 0; i < Attr.size(); i++)
{
if (!WriteConsoleOutputCharacter(hConsole, Str[i], ReadBufferSize, coordScreen, &cCharsWritten))
SLog += StringFromFormat("WriteConsoleOutputCharacter error");
if (!WriteConsoleOutputAttribute(hConsole, Attr[i], ReadBufferSize, coordScreen, &cAttrWritten))
SLog += StringFromFormat("WriteConsoleOutputAttribute error");
BytesWritten += cAttrWritten;
coordScreen = GetCoordinates(BytesWritten, LBufWidth);
}
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// Update cursor
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
int OldCursor = ConInfo.dwCursorPosition.Y * ConInfo.dwSize.X + ConInfo.dwCursorPosition.X;
COORD Coo = GetCoordinates(OldCursor, LBufWidth);
SetConsoleCursorPosition(hConsole, Coo);
// ---------------------------------------------------------------------
if (SLog.length() > 0) Log(LogTypes::LNOTICE, SLog.c_str());
// Resize the window too
if (Resize) MoveWindow(GetConsoleWindow(), Left,Top, (Width + 50),(Height + 50), true);
// Logging
//Log(LogTypes::LNOTICE, StringFromFormat("\n\n\n\nMaxBytes: %i, WxH:%ix%i, Consize: %i, Read: %i, Written: %i\n\n", MAX_BYTES, LWidth, LHeight, dwConSize, cCharsRead, cCharsWritten).c_str());
if (Resize) MoveWindow(GetConsoleWindow(), Left,Top, (Width + 100),Height, true);
#endif
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -226,7 +322,7 @@ void ConsoleListener::Log(LogTypes::LOG_LEVELS Level, const char *Text)
}
// Clear console screen
void ConsoleListener::ClearScreen()
void ConsoleListener::ClearScreen(bool Cursor)
{
#if defined(_WIN32)
COORD coordScreen = { 0, 0 };
@ -243,7 +339,7 @@ void ConsoleListener::ClearScreen()
GetConsoleScreenBufferInfo(hConsole, &csbi);
FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten);
// Reset cursor
SetConsoleCursorPosition(hConsole, coordScreen);
if (Cursor) SetConsoleCursorPosition(hConsole, coordScreen);
#endif
}
////////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -82,6 +82,7 @@ enum LOG_LEVELS {
LWARNING = WARNING_LEVEL,
LINFO = INFO_LEVEL,
LDEBUG = DEBUG_LEVEL,
LCUSTOM = CUSTOM_LEVEL,
};
} // namespace

View File

@ -78,10 +78,14 @@ public:
void Close();
bool IsOpen();
void LetterSpace(int Width, int Height);
void BufferWidthHeight(int BufferWidth, int BufferHeight, int ScreenWidth, int ScreenHeight, bool BufferFirst);
void PixelSpace(int Left, int Top, int Width, int Height, bool);
#ifdef _WIN32
COORD GetCoordinates(int BytesRead, int BufferWidth);
#endif
void Log(LogTypes::LOG_LEVELS, const char *Text);
//void Log(LogTypes::LOG_LEVELS, const char *Text, ...);
void ClearScreen();
void ClearScreen(bool Cursor = true);
const char *getName() const { return "Console"; }
@ -89,7 +93,6 @@ private:
#ifdef _WIN32
HWND GetHwnd(void);
HANDLE hConsole;
static const int MAX_BYTES = 1024 * 30;
#endif
};

View File

@ -82,6 +82,22 @@ extern "C" {
};
//////////////////////////////////////////////////////////////////////////////////////////
// Empty wxPanel
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯
BEGIN_EVENT_TABLE(CEmptyPanel, wxPanel)
END_EVENT_TABLE()
CEmptyPanel::CEmptyPanel(
wxWindow *parent,
wxWindowID id
)
: wxPanel(parent, id)
{
}
//////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////
/* Windows functions. Setting the cursor with wxSetCursor() did not work in this instance.
Probably because it's somehow reset from the WndProc() in the child window */

View File

@ -276,4 +276,17 @@ class CFrame : public wxFrame
DECLARE_EVENT_TABLE();
};
class CEmptyPanel : public wxPanel
{
public:
CEmptyPanel(
wxWindow* parent,
wxWindowID id = wxID_ANY
);
private:
DECLARE_EVENT_TABLE();
};
#endif // __FRAME_H_

View File

@ -755,12 +755,49 @@ void CFrame::ResizeConsole()
{
if (m_NB[i]->GetPageText(j).IsSameAs(wxT("Console")))
{
#ifdef _WIN32
// ----------------------------------------------------------
// Get OS version
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
int wxBorder, Border, LowerBorder, MenuBar, ScrollBar, WidthReduction;
OSVERSIONINFO osvi;
ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osvi);
if (osvi.dwMajorVersion == 6) // Vista (same as 7?)
{
wxBorder = 2;
Border = 4;
LowerBorder = 6;
MenuBar = 30; // Including upper border
ScrollBar = 19;
}
else // XP
{
wxBorder = 2;
Border = 4;
LowerBorder = 6;
MenuBar = 30;
ScrollBar = 19;
}
WidthReduction = 30 - Border;
// --------------------------------
// Get the client size
int X = m_NB[i]->GetClientSize().GetX() - 35;
int Y = m_NB[i]->GetClientSize().GetY() - 70;
int X = m_NB[i]->GetClientSize().GetX();
int Y = m_NB[i]->GetClientSize().GetY();
int InternalWidth = X - wxBorder*2 - ScrollBar;
int InternalHeight = Y - wxBorder*2;
int WindowWidth = InternalWidth + Border*2;
int WindowHeight = InternalHeight;
// Resize buffer
ConsoleListener* Console = LogManager::GetInstance()->getConsoleListener();
Console->PixelSpace(0,0, X,Y, false);
Console->Log(LogTypes::LNOTICE, StringFromFormat("Window WxH:%i %i\n", X, Y).c_str());
Console->PixelSpace(0,0, InternalWidth,InternalHeight, false);
// Move the window to hide the border
MoveWindow(GetConsoleWindow(), -Border-wxBorder,-MenuBar-wxBorder, WindowWidth + 100,WindowHeight, true);
// Move it to the bottom of the view order so that it doesn't hide the notebook tabs
// ...
#endif
}
}
}
@ -1150,7 +1187,12 @@ void CFrame::ToggleConsole(bool Show, int i)
// Can we remove the border?
//Win->SetWindowStyleFlag(wxNO_BORDER);
//SetWindowLong(GetConsoleWindow(), GWL_STYLE, WS_VISIBLE);
if (Win) m_NB[i]->AddPage(Win, wxT("Console"), true, aNormalFile );
// Create parent window
CEmptyPanel * ConsoleParent = new CEmptyPanel(this);
::SetParent(GetConsoleWindow(), (HWND)ConsoleParent->GetHWND());
//Win->SetParent(ConsoleParent);
//if (Win) m_NB[i]->AddPage(Win, wxT("Console"), true, aNormalFile );
if (Win) m_NB[i]->AddPage(ConsoleParent, wxT("Console"), true, aNormalFile );
#endif
}
else // hide