Replace standard message boxes with my own, which will word-wrap
consistently across multiple versionf of Windows, and perhaps not be immediately ignored by the user. [git-p4: depot-paths = "//depot/solvespace/": change = 2108]
This commit is contained in:
parent
342729d9a4
commit
aaf0984882
|
@ -176,7 +176,7 @@ void SolveSpace::ExportViewOrWireframeTo(char *filename, bool wireframe) {
|
|||
out);
|
||||
}
|
||||
|
||||
if(!out->HasCanvasSize()) {
|
||||
if(out && !out->HasCanvasSize()) {
|
||||
// These file formats don't have a canvas size, so they just
|
||||
// get exported in the raw coordinate system. So indicate what
|
||||
// that was on-screen.
|
||||
|
|
|
@ -789,7 +789,8 @@ void SolveSpace::MenuHelp(int id) {
|
|||
Message("This is SolveSpace version 1.6.\r\n\r\n"
|
||||
"For more information, see http://solvespace.com/\r\n\r\n"
|
||||
"Built " __TIME__ " " __DATE__ ".\r\n\r\n"
|
||||
"Copyright 2008-2010 Useful Subset, LLC. All Rights Reserved.");
|
||||
"Copyright 2008-2010 Useful Subset, LLC.\r\n"
|
||||
"All Rights Reserved.");
|
||||
break;
|
||||
|
||||
case GraphicsWindow::MNU_LICENSE: {
|
||||
|
|
|
@ -152,8 +152,7 @@ void dbp(char *str, ...);
|
|||
CO((tri).a), CO((tri).b), CO((tri).c))
|
||||
|
||||
void SetWindowTitle(char *str);
|
||||
void Message(char *str, ...);
|
||||
void Error(char *str, ...);
|
||||
void DoMessageBox(char *str, int rows, int cols, BOOL error);
|
||||
void SetTimerFor(int milliseconds);
|
||||
void ExitNow(void);
|
||||
|
||||
|
@ -235,6 +234,8 @@ void MakePathRelative(char *base, char *path);
|
|||
void MakePathAbsolute(char *base, char *path);
|
||||
bool StringAllPrintable(char *str);
|
||||
bool StringEndsIn(char *str, char *ending);
|
||||
void Message(char *str, ...);
|
||||
void Error(char *str, ...);
|
||||
|
||||
class System {
|
||||
public:
|
||||
|
|
75
util.cpp
75
util.cpp
|
@ -125,6 +125,81 @@ void MakeMatrix(double *mat, double a11, double a12, double a13, double a14,
|
|||
mat[15] = a44;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Word-wrap the string for our message box appropriately, and then display
|
||||
// that string.
|
||||
//-----------------------------------------------------------------------------
|
||||
static void DoStringForMessageBox(char *str, va_list f, bool error)
|
||||
{
|
||||
char inBuf[1024*50];
|
||||
vsprintf(inBuf, str, f);
|
||||
|
||||
char outBuf[1024*50];
|
||||
int i = 0, j = 0, len = 0, longestLen = 47;
|
||||
int rows = 0, cols = 0;
|
||||
|
||||
// Count the width of the longest line that starts with spaces; those
|
||||
// are list items, that should not be split in the middle.
|
||||
bool listLine = false;
|
||||
while(inBuf[i]) {
|
||||
if(inBuf[i] == '\r') {
|
||||
// ignore these
|
||||
} else if(inBuf[i] == ' ' && len == 0) {
|
||||
listLine = true;
|
||||
} else if(inBuf[i] == '\n') {
|
||||
if(listLine) longestLen = max(longestLen, len);
|
||||
len = 0;
|
||||
} else {
|
||||
len++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if(listLine) longestLen = max(longestLen, len);
|
||||
|
||||
// Word wrap according to our target line length longestLen.
|
||||
len = 0;
|
||||
i = 0;
|
||||
while(inBuf[i]) {
|
||||
if(inBuf[i] == '\r') {
|
||||
// ignore these
|
||||
} else if(inBuf[i] == '\n') {
|
||||
outBuf[j++] = '\n';
|
||||
if(len == 0) rows++;
|
||||
len = 0;
|
||||
} else if(inBuf[i] == ' ' && len > longestLen) {
|
||||
outBuf[j++] = '\n';
|
||||
len = 0;
|
||||
} else {
|
||||
outBuf[j++] = inBuf[i];
|
||||
// Count rows when we draw the first character; so an empty
|
||||
// row doesn't end up counting.
|
||||
if(len == 0) rows++;
|
||||
len++;
|
||||
}
|
||||
cols = max(cols, len);
|
||||
i++;
|
||||
}
|
||||
outBuf[j++] = '\0';
|
||||
|
||||
// And then display the text with our actual longest line length.
|
||||
DoMessageBox(outBuf, rows, cols, error);
|
||||
}
|
||||
void Error(char *str, ...)
|
||||
{
|
||||
va_list f;
|
||||
va_start(f, str);
|
||||
DoStringForMessageBox(str, f, true);
|
||||
va_end(f);
|
||||
}
|
||||
void Message(char *str, ...)
|
||||
{
|
||||
va_list f;
|
||||
va_start(f, str);
|
||||
DoStringForMessageBox(str, f, false);
|
||||
va_end(f);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Solve a mostly banded matrix. In a given row, there are LEFT_OF_DIAG
|
||||
// elements to the left of the diagonal element, and RIGHT_OF_DIAG elements to
|
||||
|
|
|
@ -58,42 +58,141 @@ HFONT FixedFont, LinkFont;
|
|||
// The 6-DOF input device.
|
||||
SiHdl SpaceNavigator = SI_NO_HANDLE;
|
||||
|
||||
static void DoMessageBox(char *str, va_list f, BOOL error)
|
||||
{
|
||||
char buf[1024*50];
|
||||
vsprintf(buf, str, f);
|
||||
//-----------------------------------------------------------------------------
|
||||
// Routines to display message boxes on screen. Do our own, instead of using
|
||||
// MessageBox, because that is not consistent from version to version and
|
||||
// there's word wrap problems.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
HWND MessageWnd, OkButton;
|
||||
BOOL MessageDone;
|
||||
char *MessageString;
|
||||
|
||||
static LRESULT CALLBACK MessageProc(HWND hwnd, UINT msg, WPARAM wParam,
|
||||
LPARAM lParam)
|
||||
{
|
||||
switch (msg) {
|
||||
case WM_COMMAND:
|
||||
if((HWND)lParam == OkButton && wParam == BN_CLICKED) {
|
||||
MessageDone = TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_CLOSE:
|
||||
case WM_DESTROY:
|
||||
MessageDone = TRUE;
|
||||
break;
|
||||
|
||||
case WM_PAINT: {
|
||||
PAINTSTRUCT ps;
|
||||
HDC hdc = BeginPaint(hwnd, &ps);
|
||||
int row = 0, col = 0, i;
|
||||
SelectObject(hdc, FixedFont);
|
||||
SetTextColor(hdc, RGB(0, 0, 0));
|
||||
SetBkMode(hdc, TRANSPARENT);
|
||||
for(i = 0; MessageString[i]; i++) {
|
||||
if(MessageString[i] == '\n') {
|
||||
col = 0;
|
||||
row++;
|
||||
} else {
|
||||
TextOut(hdc, col*TEXT_WIDTH + 10, row*TEXT_HEIGHT + 10,
|
||||
&(MessageString[i]), 1);
|
||||
col++;
|
||||
}
|
||||
}
|
||||
EndPaint(hwnd, &ps);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return DefWindowProc(hwnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
HWND CreateWindowClient(DWORD exStyle, char *className, char *windowName,
|
||||
DWORD style, int x, int y, int width, int height, HWND parent,
|
||||
HMENU menu, HINSTANCE instance, void *param)
|
||||
{
|
||||
HWND h = CreateWindowEx(exStyle, className, windowName, style, x, y,
|
||||
width, height, parent, menu, instance, param);
|
||||
|
||||
RECT r;
|
||||
GetClientRect(h, &r);
|
||||
width = width - (r.right - width);
|
||||
height = height - (r.bottom - height);
|
||||
|
||||
SetWindowPos(h, HWND_TOP, x, y, width, height, 0);
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
void DoMessageBox(char *str, int rows, int cols, BOOL error)
|
||||
{
|
||||
EnableWindow(GraphicsWnd, FALSE);
|
||||
EnableWindow(TextWnd, FALSE);
|
||||
|
||||
int flags;
|
||||
if(error) {
|
||||
flags = MB_OK | MB_ICONERROR;
|
||||
} else {
|
||||
flags = MB_OK | MB_ICONINFORMATION;
|
||||
}
|
||||
HWND h = GetForegroundWindow();
|
||||
MessageBox(h, buf, "SolveSpace", flags);
|
||||
|
||||
// Register the window class for our dialog.
|
||||
WNDCLASSEX wc;
|
||||
memset(&wc, 0, sizeof(wc));
|
||||
wc.cbSize = sizeof(wc);
|
||||
wc.style = CS_BYTEALIGNCLIENT | CS_BYTEALIGNWINDOW | CS_OWNDC;
|
||||
wc.lpfnWndProc = (WNDPROC)MessageProc;
|
||||
wc.hInstance = Instance;
|
||||
wc.hbrBackground = (HBRUSH)COLOR_BTNSHADOW;
|
||||
wc.lpszClassName = "MessageWnd";
|
||||
wc.lpszMenuName = NULL;
|
||||
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
wc.hIcon = (HICON)LoadImage(Instance, MAKEINTRESOURCE(4000),
|
||||
IMAGE_ICON, 32, 32, 0);
|
||||
wc.hIconSm = (HICON)LoadImage(Instance, MAKEINTRESOURCE(4000),
|
||||
IMAGE_ICON, 16, 16, 0);
|
||||
RegisterClassEx(&wc);
|
||||
|
||||
// Create the window.
|
||||
MessageString = str;
|
||||
RECT r;
|
||||
GetWindowRect(GraphicsWnd, &r);
|
||||
char *title = error ? "SolveSpace - Error" : "SolveSpace - Message";
|
||||
int width = cols*TEXT_WIDTH + 20, height = rows*TEXT_HEIGHT + 60;
|
||||
MessageWnd = CreateWindowClient(0, "MessageWnd", title,
|
||||
WS_OVERLAPPED | WS_SYSMENU,
|
||||
r.left + 100, r.top + 100, width, height, NULL, NULL, Instance, NULL);
|
||||
|
||||
OkButton = CreateWindowEx(0, WC_BUTTON, "OK",
|
||||
WS_CHILD | WS_TABSTOP | WS_CLIPSIBLINGS | WS_VISIBLE | BS_DEFPUSHBUTTON,
|
||||
(width - 70)/2, rows*TEXT_HEIGHT + 20,
|
||||
70, 25, MessageWnd, NULL, Instance, NULL);
|
||||
SendMessage(OkButton, WM_SETFONT, (WPARAM)FixedFont, TRUE);
|
||||
|
||||
ShowWindow(MessageWnd, TRUE);
|
||||
SetFocus(OkButton);
|
||||
|
||||
MSG msg;
|
||||
DWORD ret;
|
||||
MessageDone = FALSE;
|
||||
while((ret = GetMessage(&msg, NULL, 0, 0)) && !MessageDone) {
|
||||
if((msg.message == WM_KEYDOWN &&
|
||||
(msg.wParam == VK_RETURN ||
|
||||
msg.wParam == VK_ESCAPE)) ||
|
||||
(msg.message == WM_KEYUP &&
|
||||
(msg.wParam == VK_SPACE)))
|
||||
{
|
||||
MessageDone = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
|
||||
MessageString = NULL;
|
||||
EnableWindow(TextWnd, TRUE);
|
||||
EnableWindow(GraphicsWnd, TRUE);
|
||||
SetForegroundWindow(GraphicsWnd);
|
||||
}
|
||||
|
||||
void Error(char *str, ...)
|
||||
{
|
||||
va_list f;
|
||||
va_start(f, str);
|
||||
DoMessageBox(str, f, TRUE);
|
||||
va_end(f);
|
||||
}
|
||||
|
||||
void Message(char *str, ...)
|
||||
{
|
||||
va_list f;
|
||||
va_start(f, str);
|
||||
DoMessageBox(str, f, FALSE);
|
||||
va_end(f);
|
||||
DestroyWindow(MessageWnd);
|
||||
}
|
||||
|
||||
void AddContextMenuItem(char *label, int id)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
better Error() and Message() dialog boxes
|
||||
replace show/hide links with icons?
|
||||
lock point where dragged constraint
|
||||
projected and signed distance constraints
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user