2013-03-30 13:05:37 -04:00
|
|
|
#include <PreviewWindow.hpp>
|
|
|
|
|
|
|
|
#include <resource.h>
|
|
|
|
#include <windowsx.h>
|
|
|
|
|
|
|
|
LRESULT PreviewWindow::OnCreate()
|
|
|
|
{
|
|
|
|
NONCLIENTMETRICS ncmMetrics = { sizeof(NONCLIENTMETRICS) };
|
|
|
|
RECT client;
|
|
|
|
|
|
|
|
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncmMetrics, 0);
|
|
|
|
GetClientRect(m_hwnd, &client);
|
|
|
|
|
|
|
|
hFont = CreateFontIndirect(&ncmMetrics.lfMessageFont);
|
|
|
|
|
|
|
|
// Get the handle to the client area's device context.
|
|
|
|
HDC hdc = GetDC(m_hwnd);
|
|
|
|
TEXTMETRIC tm;
|
|
|
|
// Extract font dimensions from the text metrics.
|
|
|
|
GetTextMetrics(hdc, &tm);
|
|
|
|
xChar = tm.tmAveCharWidth;
|
|
|
|
xUpper =(tm.tmPitchAndFamily & 1 ? 3 : 2) * xChar/2;
|
|
|
|
yChar = tm.tmHeight + tm.tmExternalLeading;
|
|
|
|
// Free the device context.
|
|
|
|
ReleaseDC(m_hwnd, hdc);
|
|
|
|
// Set an arbitrary maximum width for client area.
|
|
|
|
//(xClientMax is the sum of the widths of 48 average
|
|
|
|
// lowercase letters and 12 uppercase letters.)
|
|
|
|
xClientMax = 48 * xChar + 12 * xUpper;
|
|
|
|
|
|
|
|
lpLines = NULL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
LRESULT PreviewWindow::OnDestroy()
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
HICON PreviewWindow::GetIcon()
|
|
|
|
{
|
|
|
|
return LoadIcon(GetInstance(), MAKEINTRESOURCE(RID_ICON));
|
|
|
|
}
|
|
|
|
|
|
|
|
void PreviewWindow::OnPaint()
|
|
|
|
{
|
|
|
|
PAINTSTRUCT ps;
|
|
|
|
SCROLLINFO si;
|
|
|
|
RECT rect;
|
|
|
|
|
|
|
|
BeginPaint(m_hwnd, &ps);
|
|
|
|
GetClientRect(m_hwnd, &rect);
|
|
|
|
|
|
|
|
if (empty)
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
si.cbSize = sizeof(si);
|
|
|
|
si.fMask = SIF_POS;
|
|
|
|
GetScrollInfo(m_hwnd, SB_VERT, &si);
|
|
|
|
yPos = si.nPos;
|
|
|
|
|
|
|
|
SelectObject(ps.hdc, hFont);
|
|
|
|
SetBkColor(ps.hdc, RGB(0xF0, 0xF0, 0xF0));
|
|
|
|
// Find painting limits.
|
|
|
|
int FirstLine = max(0, yPos + ps.rcPaint.top / yChar);
|
|
|
|
int LastLine = min(lines - 1, yPos + ps.rcPaint.bottom / yChar);
|
|
|
|
|
|
|
|
// Get horizontal scroll bar position.
|
|
|
|
GetScrollInfo(m_hwnd, SB_HORZ, &si);
|
|
|
|
xPos = si.nPos;
|
|
|
|
for (int i = FirstLine; i <= LastLine; i++) {
|
|
|
|
int x = xChar *(1 - xPos);
|
|
|
|
int y = yChar *(i - yPos);
|
|
|
|
rect.top = y;
|
|
|
|
rect.left = x;
|
|
|
|
DrawText(ps.hdc, lpLines[i], -1, &rect, DT_NOCLIP);
|
|
|
|
}
|
|
|
|
done:
|
|
|
|
EndPaint(m_hwnd, &ps);
|
|
|
|
}
|
|
|
|
|
|
|
|
LRESULT PreviewWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
|
|
|
switch(uMsg) {
|
|
|
|
case WM_CREATE:
|
|
|
|
return OnCreate();
|
|
|
|
case WM_DESTROY:
|
|
|
|
return OnDestroy();
|
|
|
|
case WM_NCDESTROY:
|
|
|
|
PostQuitMessage(0);
|
|
|
|
break;
|
|
|
|
case WM_PAINT:
|
|
|
|
OnPaint();
|
|
|
|
return 0;
|
|
|
|
case WM_SIZE: {
|
|
|
|
RECT client;
|
|
|
|
SCROLLINFO si;
|
|
|
|
|
|
|
|
GetClientRect(m_hwnd, &client);
|
|
|
|
yClient = client.bottom - client.top;
|
|
|
|
xClient = client.right - client.left;
|
|
|
|
|
|
|
|
// Set the vertical scrolling range and page size
|
|
|
|
si.cbSize = sizeof(si);
|
|
|
|
si.fMask = SIF_RANGE | SIF_PAGE;
|
|
|
|
si.nMin = 0;
|
|
|
|
si.nMax = lines - 1;
|
|
|
|
si.nPage = yClient / yChar;
|
|
|
|
SetScrollInfo(m_hwnd, SB_VERT, &si, TRUE);
|
|
|
|
|
|
|
|
// Set the horizontal scrolling range and page size.
|
|
|
|
si.cbSize = sizeof(si);
|
|
|
|
si.fMask = SIF_RANGE | SIF_PAGE;
|
|
|
|
si.nMin = 0;
|
|
|
|
si.nMax = 2 + xClientMax / xChar;
|
|
|
|
si.nPage = xClient / xChar;
|
|
|
|
SetScrollInfo(m_hwnd, SB_HORZ, &si, TRUE);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
case WM_HSCROLL: {
|
|
|
|
SCROLLINFO si;
|
|
|
|
// Get all the vertial scroll bar information.
|
|
|
|
si.cbSize = sizeof(si);
|
|
|
|
si.fMask = SIF_ALL;
|
|
|
|
|
|
|
|
// Save the position for comparison later on.
|
|
|
|
GetScrollInfo(m_hwnd, SB_HORZ, &si);
|
|
|
|
xPos = si.nPos;
|
|
|
|
switch(LOWORD(wParam)) {
|
|
|
|
// User clicked the left arrow.
|
|
|
|
case SB_LINELEFT:
|
|
|
|
si.nPos -= 1;
|
|
|
|
break;
|
|
|
|
// User clicked the right arrow.
|
|
|
|
case SB_LINERIGHT:
|
|
|
|
si.nPos += 1;
|
|
|
|
break;
|
|
|
|
// User clicked the scroll bar shaft left of the scroll box.
|
|
|
|
case SB_PAGELEFT:
|
|
|
|
si.nPos -= si.nPage;
|
|
|
|
break;
|
|
|
|
// User clicked the scroll bar shaft right of the scroll box.
|
|
|
|
case SB_PAGERIGHT:
|
|
|
|
si.nPos += si.nPage;
|
|
|
|
break;
|
|
|
|
// User dragged the scroll box.
|
|
|
|
case SB_THUMBTRACK:
|
|
|
|
si.nPos = si.nTrackPos;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Set the position and then retrieve it. Due to adjustments
|
|
|
|
// by Windows it may not be the same as the value set.
|
|
|
|
si.fMask = SIF_POS;
|
|
|
|
SetScrollInfo(m_hwnd, SB_HORZ, &si, TRUE);
|
|
|
|
GetScrollInfo(m_hwnd, SB_HORZ, &si);
|
|
|
|
|
|
|
|
// If the position has changed, scroll the window.
|
|
|
|
if(si.nPos != xPos)
|
|
|
|
ScrollWindow(m_hwnd, xChar *(xPos - si.nPos), 0, NULL, NULL);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
case WM_VSCROLL: {
|
|
|
|
SCROLLINFO si;
|
|
|
|
// Get all the vertial scroll bar information.
|
|
|
|
si.cbSize = sizeof(si);
|
|
|
|
si.fMask = SIF_ALL;
|
|
|
|
GetScrollInfo(m_hwnd, SB_VERT, &si);
|
|
|
|
|
|
|
|
// Save the position for comparison later on.
|
|
|
|
yPos = si.nPos;
|
|
|
|
switch(LOWORD(wParam)) {
|
|
|
|
// User clicked the HOME keyboard key.
|
|
|
|
case SB_TOP:
|
|
|
|
si.nPos = si.nMin;
|
|
|
|
break;
|
|
|
|
// User clicked the END keyboard key.
|
|
|
|
case SB_BOTTOM:
|
|
|
|
si.nPos = si.nMax;
|
|
|
|
break;
|
|
|
|
// User clicked the top arrow.
|
|
|
|
case SB_LINEUP:
|
|
|
|
si.nPos -= 1;
|
|
|
|
break;
|
|
|
|
// User clicked the bottom arrow.
|
|
|
|
case SB_LINEDOWN:
|
|
|
|
si.nPos += 1;
|
|
|
|
break;
|
|
|
|
// User clicked the scroll bar shaft above the scroll box.
|
|
|
|
case SB_PAGEUP:
|
|
|
|
si.nPos -= si.nPage;
|
|
|
|
break;
|
|
|
|
// User clicked the scroll bar shaft below the scroll box.
|
|
|
|
case SB_PAGEDOWN:
|
|
|
|
si.nPos += si.nPage;
|
|
|
|
break;
|
|
|
|
// User dragged the scroll box.
|
|
|
|
case SB_THUMBTRACK:
|
|
|
|
si.nPos = si.nTrackPos;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Set the position and then retrieve it. Due to adjustments
|
|
|
|
// by Windows it may not be the same as the value set.
|
|
|
|
si.fMask = SIF_POS;
|
|
|
|
SetScrollInfo(m_hwnd, SB_VERT, &si, TRUE);
|
|
|
|
GetScrollInfo(m_hwnd, SB_VERT, &si);
|
|
|
|
|
|
|
|
// If the position has changed, scroll window and update it.
|
|
|
|
if(si.nPos != yPos) {
|
|
|
|
ScrollWindow(m_hwnd, 0, yChar *(yPos - si.nPos), NULL, NULL);
|
|
|
|
UpdateWindow(m_hwnd);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
case WM_MOUSEWHEEL: {
|
|
|
|
SCROLLINFO si;
|
|
|
|
// Get all the vertial scroll bar information.
|
|
|
|
si.cbSize = sizeof(si);
|
|
|
|
si.fMask = SIF_ALL;
|
|
|
|
GetScrollInfo(m_hwnd, SB_VERT, &si);
|
|
|
|
yPos = si.nPos;
|
|
|
|
|
|
|
|
si.nPos -= GET_WHEEL_DELTA_WPARAM(wParam) / WHEEL_DELTA;
|
|
|
|
si.fMask = SIF_POS;
|
|
|
|
SetScrollInfo(m_hwnd, SB_VERT, &si, TRUE);
|
|
|
|
GetScrollInfo(m_hwnd, SB_VERT, &si);
|
|
|
|
|
|
|
|
if(si.nPos != yPos) {
|
|
|
|
ScrollWindow(m_hwnd, 0, yChar *(yPos - si.nPos), NULL, NULL);
|
|
|
|
UpdateWindow(m_hwnd);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
case WM_CHANGETEXT: {
|
|
|
|
if (lpLines) {
|
|
|
|
for (int i = 0; i < lines; ++i)
|
|
|
|
delete [] lpLines[i];
|
|
|
|
delete [] lpLines;
|
|
|
|
}
|
|
|
|
|
|
|
|
LPTSTR str = (LPTSTR) lParam;
|
|
|
|
int l = 0, longest = 0, maxlen = 0;
|
|
|
|
|
|
|
|
if (*str == L'\0') {
|
|
|
|
empty = true;
|
|
|
|
lpLines = NULL;
|
|
|
|
} else empty = false;
|
|
|
|
|
|
|
|
while (*str++)
|
|
|
|
if (*str == L'\n')
|
|
|
|
++l;
|
|
|
|
|
|
|
|
if (*(str-1) != L'\n')
|
|
|
|
++l;
|
|
|
|
|
|
|
|
lines = l + 8;
|
|
|
|
lpLines = new LPTSTR[lines];
|
|
|
|
for (int i = 0; i < 4; ++i) {
|
|
|
|
lpLines[i] = new TCHAR[1];
|
|
|
|
lpLines[i][0] = L'\0';
|
|
|
|
}
|
|
|
|
str = (LPTSTR) lParam;
|
|
|
|
for (int i = 0; i < l; ++i) {
|
|
|
|
LPTSTR start = str, end, buf;
|
|
|
|
int len;
|
|
|
|
while (*str++ != L'\n' && *(str-1) != L'\0');
|
|
|
|
end = str - 1;
|
|
|
|
len = end - start;
|
|
|
|
if (len > maxlen) {
|
|
|
|
longest = i+4;
|
|
|
|
maxlen = len;
|
|
|
|
}
|
|
|
|
buf = new TCHAR[len + 1];
|
|
|
|
memcpy(buf, start, len*sizeof(TCHAR));
|
|
|
|
buf[len] = L'\0';
|
|
|
|
lpLines[i+4] = buf;
|
|
|
|
}
|
|
|
|
for (int i = l + 4; i < lines; ++i) {
|
|
|
|
lpLines[i] = new TCHAR[1];
|
|
|
|
lpLines[i][0] = L'\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
int upper = 0, lower = 0;
|
|
|
|
for (LPTSTR i = lpLines[longest]; *i; ++i) {
|
|
|
|
if (isupper(*i))
|
|
|
|
++upper;
|
2013-06-03 23:24:53 -04:00
|
|
|
else if (!(*i >= 0x0300 && *i < 0x0370 || *i == 0x489))
|
2013-03-30 13:05:37 -04:00
|
|
|
++lower;
|
|
|
|
}
|
|
|
|
xClientMax = lower * xChar + upper * xUpper;
|
|
|
|
|
|
|
|
PostMessage(m_hwnd, WM_SIZE, 0, 0);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
case WM_CLOSE:
|
|
|
|
ShowWindow(m_hwnd, SW_HIDE);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return __super::HandleMessage(uMsg, wParam, lParam);
|
|
|
|
}
|
|
|
|
|
|
|
|
PreviewWindow *PreviewWindow::Create(LPCTSTR szTitle)
|
|
|
|
{
|
|
|
|
PreviewWindow *self = new PreviewWindow();
|
|
|
|
if(self &&
|
|
|
|
self->WinCreateWindow(0,
|
|
|
|
szTitle, WS_OVERLAPPEDWINDOW,
|
|
|
|
CW_USEDEFAULT, CW_USEDEFAULT, 640, 480,
|
|
|
|
NULL, NULL)) {
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
delete self;
|
|
|
|
return NULL;
|
|
|
|
}
|