[CHARMAP_NEW]

- Implement drawing fonts onto the gridview
- Implement scrolling through the grid via the scrollbar
- When a new font is selected, setup that font for drawing. This includes setting up the DC for painting, getting the valid glyphs for that font (this fixes the bug in the existing viewer which has lots of squares for glyphs), setting up scrollbar info, etc.
- Make the cell object more responsible for its own painting
CORE-10518

svn path=/trunk/; revision=70098
This commit is contained in:
Ged Murphy 2015-11-24 17:55:27 +00:00
parent 68efaa6696
commit b841070c1a
7 changed files with 282 additions and 53 deletions

View file

@ -29,7 +29,7 @@ CCell::CCell(
) :
m_hParent(hParent),
m_CellCoordinates(CellCoordinates),
ch(L'*'),
m_Char(L'*'),
m_bHasFocus(false),
m_bIsLarge(false)
{
@ -50,21 +50,23 @@ CCell::OnPaint(_In_ PAINTSTRUCT &PaintStruct)
if (NeedsPaint == FALSE)
return false;
// Draw the cell border
BOOL b = Rectangle(PaintStruct.hdc,
m_CellCoordinates.left,
m_CellCoordinates.top,
m_CellCoordinates.right,
m_CellCoordinates.bottom);
m_CellCoordinates.left,
m_CellCoordinates.top,
m_CellCoordinates.right,
m_CellCoordinates.bottom);
// Calculate an internal drawing canvas for the cell
RECT Internal;
CopyRect(&Internal, &m_CellCoordinates);
InflateRect(&Internal, -1, -1);
// Check if this cell has focus
if (m_bHasFocus)
{
// Take a copy of the border dims and make it slightly smaller
RECT Internal;
CopyRect(&Internal, &m_CellCoordinates);
InflateRect(&Internal, -1, -1);
// Draw the smaller cell to make it look selected
Rectangle(PaintStruct.hdc,
Internal.left,
@ -73,7 +75,14 @@ CCell::OnPaint(_In_ PAINTSTRUCT &PaintStruct)
Internal.bottom);
}
return true;
int Success;
Success = DrawTextW(PaintStruct.hdc,
&m_Char,
1,
&Internal,
DT_CENTER | DT_VCENTER | DT_SINGLELINE);
return (Success != 0);
}
void

View file

@ -7,7 +7,7 @@ private:
bool m_bHasFocus;
bool m_bIsLarge;
WCHAR ch;
WCHAR m_Char;
public:
CCell(
@ -23,6 +23,8 @@ public:
LPRECT GetCellCoordinates() { return &m_CellCoordinates; }
void SetFocus(_In_ bool HasFocus) { m_bHasFocus = HasFocus; }
WCHAR GetChar() { return m_Char; }
void SetChar(_In_ WCHAR ch) { m_Char = ch; }
bool OnPaint(
_In_ PAINTSTRUCT &PaintStruct

View file

@ -21,7 +21,8 @@ extern HINSTANCE g_hInstance;
CGridView::CGridView() :
m_xNumCells(20),
m_yNumCells(10)
m_yNumCells(10),
ScrollPosition(0)
{
m_szMapWndClass = L"CharGridWClass";
}
@ -62,7 +63,94 @@ CGridView::Create(
}
bool
CGridView::UpdateGridLayout(
CGridView::SetFont(
_In_ CAtlString& FontName
)
{
// Create a temperary container for the new font
CurrentFont NewFont = { 0 };
NewFont.FontName = FontName;
// Get the DC for the full grid window
HDC hdc;
hdc = GetDC(m_hwnd);
if (hdc == NULL) return false;
// Setup the logfont structure
NewFont.Font.lfHeight = GetDeviceCaps(hdc, LOGPIXELSY) / 5;
NewFont.Font.lfCharSet = DEFAULT_CHARSET;
StringCchCopyW(NewFont.Font.lfFaceName, LF_FACESIZE, FontName);
// Get a handle to the new font
NewFont.hFont = CreateFontIndirectW(&NewFont.Font);
if (NewFont.hFont == NULL)
{
ReleaseDC(m_hwnd, hdc);
return false;
}
// Setup an array of all possible non-BMP indices
WCHAR ch[MAX_GLYPHS];
for (int i = 0; i < MAX_GLYPHS; i++)
ch[i] = (WCHAR)i;
HFONT hOldFont;
hOldFont = (HFONT)SelectObject(hdc, NewFont.hFont);
// Translate all the indices into glyphs
WORD out[MAX_GLYPHS];
DWORD Status;
Status = GetGlyphIndicesW(hdc,
ch,
MAX_GLYPHS,
out,
GGI_MARK_NONEXISTING_GLYPHS);
ReleaseDC(m_hwnd, hdc);
if (Status == GDI_ERROR)
{
SelectObject(hdc, hOldFont);
return false;
}
// Loop all the glyphs looking for valid ones
// and store those in our font data
int j = 0;
for (int i = 0; i < MAX_GLYPHS; i++)
{
if (out[i] != 0xffff)
{
NewFont.ValidGlyphs[j] = ch[i];
j++;
}
}
NewFont.NumValidGlyphs = j;
// Calculate the number of rows required to hold all glyphs
int Rows = NewFont.NumValidGlyphs / m_xNumCells;
if (NewFont.NumValidGlyphs % m_xNumCells)
Rows += 1;
// Set the scrollbar in relation to the rows
SetScrollRange(m_hwnd, SB_VERT, 0, Rows, FALSE);
// We're done, update the current font
m_CurrentFont = NewFont;
// We changed the font, we'll need to repaint the whole window
InvalidateRect(m_hwnd,
NULL,
TRUE);
return true;
}
/* PRIVATE METHODS **********************************************/
bool
CGridView::UpdateCellCoordinates(
)
{
// Go through all the cells and calculate
@ -71,10 +159,10 @@ CGridView::UpdateGridLayout(
for (int x = 0; x < m_xNumCells; x++)
{
RECT CellCoordinates;
CellCoordinates.left = x * m_CellSize.cx + 1;
CellCoordinates.top = y * m_CellSize.cy + 1;
CellCoordinates.right = (x + 1) * m_CellSize.cx + 2;
CellCoordinates.bottom = (y + 1) * m_CellSize.cy + 2;
CellCoordinates.left = x * m_CellSize.cx;
CellCoordinates.top = y * m_CellSize.cy;
CellCoordinates.right = (x + 1) * m_CellSize.cx + 1;
CellCoordinates.bottom = (y + 1) * m_CellSize.cy + 1;
m_Cells[y][x]->SetCellCoordinates(CellCoordinates);
}
@ -125,6 +213,7 @@ CGridView::OnSize(
m_ClientCoordinates.right = ParentRect.right - m_ClientCoordinates.left - 10;
m_ClientCoordinates.bottom = ParentRect.bottom - m_ClientCoordinates.top - 70;
// Resize the grid window
SetWindowPos(m_hwnd,
NULL,
m_ClientCoordinates.left,
@ -133,20 +222,92 @@ CGridView::OnSize(
m_ClientCoordinates.bottom,
SWP_NOZORDER | SWP_SHOWWINDOW);
// Get the client area we can draw on. The position we set above
// includes a scrollbar. GetClientRect gives us the size without
// the scroll, and it more efficient than getting the scroll
// metrics and calculating the size
// Get the client area we can draw on. The position we set above includes
// a scrollbar which we obvioulsy can't draw on. GetClientRect gives us
// the size without the scroll, and it more efficient than getting the
// scroll metrics and calculating the size from that
RECT ClientRect;
GetClientRect(m_hwnd, &ClientRect);
m_CellSize.cx = ClientRect.right / m_xNumCells;
m_CellSize.cy = ClientRect.bottom / m_yNumCells;
UpdateGridLayout();
// Let all the cells know about their new coords
UpdateCellCoordinates();
return 0;
}
VOID
CGridView::OnVScroll(_In_ INT Value,
_In_ INT Pos)
{
INT PrevScrollPosition = ScrollPosition;
switch (Value)
{
case SB_LINEUP:
ScrollPosition -= 1;
break;
case SB_LINEDOWN:
ScrollPosition += 1;
break;
case SB_PAGEUP:
ScrollPosition -= m_yNumCells;
break;
case SB_PAGEDOWN:
ScrollPosition += m_yNumCells;
break;
case SB_THUMBTRACK:
ScrollPosition = Pos;
break;
default:
break;
}
INT ScrollDiff;
ScrollDiff = PrevScrollPosition - ScrollPosition;
if (ScrollDiff)
{
// Set the new scrollbar position in the scroll box
SetScrollPos(m_hwnd,
SB_VERT,
ScrollPosition,
TRUE);
// Check if the scrollbar has moved more than the
// number of visible rows (draged or paged)
if (abs(ScrollDiff) < m_yNumCells)
{
RECT rect;
GetClientRect(m_hwnd, &rect);
// Scroll the visible cells which remain within the grid
// and invalid any new ones which appear from the top / bottom
ScrollWindowEx(m_hwnd,
0,
ScrollDiff * m_CellSize.cy,
&rect,
&rect,
NULL,
NULL,
SW_INVALIDATE);
}
else
{
// All the cells need to be redrawn
InvalidateRect(m_hwnd,
NULL,
TRUE);
}
}
}
LRESULT
CGridView::OnPaint(
_In_opt_ HDC hdc
@ -176,8 +337,10 @@ CGridView::OnPaint(
}
}
// Make sure we have a valid DC
if (bSuccess)
{
// Paint the grid and chars
DrawGrid(&PaintStruct);
if (LocalHdc)
@ -237,6 +400,16 @@ CGridView::MapWndProc(
break;
}
case WM_VSCROLL:
{
INT Value, Pos;
Value = LOWORD(wParam);
Pos = HIWORD(wParam);
This->OnVScroll(Value, Pos);
break;
}
case WM_PAINT:
{
This->OnPaint((HDC)wParam);
@ -266,12 +439,29 @@ CGridView::DrawGrid(
_In_ LPPAINTSTRUCT PaintStruct
)
{
// Calculate which glyph to start at based on scroll position
int i;
i = m_xNumCells * ScrollPosition;
// Make sure we have the correct font on the DC
HFONT hOldFont;
hOldFont = (HFONT)SelectFont(PaintStruct->hdc,
m_CurrentFont.hFont);
// Traverse all the cells and tell them to paint themselves
for (int y = 0; y < m_yNumCells; y++)
for (int x = 0; x < m_xNumCells; x++)
{
WCHAR ch = (WCHAR)m_CurrentFont.ValidGlyphs[i];
m_Cells[y][x]->SetChar(ch);
m_Cells[y][x]->OnPaint(*PaintStruct);
i++;
}
SelectObject(PaintStruct->hdc, hOldFont);
}
void

View file

@ -1,18 +1,17 @@
#pragma once
#include "Cell.h"
//typedef struct _CELL
//{
// RECT CellExt;
// RECT CellInt;
// BOOL bActive;
// BOOL bLarge;
// WCHAR ch;
//
//} CELL, *PCELL;
#define MAX_GLYPHS 0xFFFF
struct CurrentFont
{
CAtlStringW FontName;
LOGFONTW Font;
HFONT hFont;
USHORT ValidGlyphs[MAX_GLYPHS];
USHORT NumValidGlyphs;
};
class CGridView
{
@ -26,17 +25,14 @@ private:
int m_yNumCells;
RECT m_ClientCoordinates;
//SIZE ClientSize;
SIZE m_CellSize;
CCell*** m_Cells; // m_Cells[][];
CCell*** m_Cells; // *m_Cells[][];
CCell *m_ActiveCell;
HFONT hFont;
LOGFONTW CurrentFont;
INT iYStart;
INT ScrollPosition;
USHORT ValidGlyphs[MAX_GLYPHS];
USHORT NumValidGlyphs;
CurrentFont m_CurrentFont;
public:
CGridView();
@ -46,6 +42,10 @@ public:
_In_ HWND hParent
);
bool SetFont(
_In_ CAtlString& FontName
);
private:
static LRESULT
CALLBACK
@ -65,11 +65,16 @@ private:
_In_ INT Height
);
VOID OnVScroll(
_In_ INT Value,
_In_ INT Pos
);
LRESULT OnPaint(
_In_opt_ HDC hdc
);
bool UpdateGridLayout(
bool UpdateCellCoordinates(
);
void DrawGrid(

View file

@ -199,6 +199,8 @@ CCharMapWindow::OnCreate(_In_ HWND hDlg)
if (!CreateFontComboBox())
return FALSE;
ChangeMapFont();
// Configure Richedit control for sending notification changes.
DWORD evMask;
evMask = SendDlgItemMessage(hDlg, IDC_TEXTBOX, EM_GETEVENTMASK, 0, 0);
@ -283,6 +285,13 @@ CCharMapWindow::OnCommand(_In_ WPARAM wParam,
case IDC_CHECK_ADVANCED:
break;
case IDC_FONTCOMBO:
if (HIWORD(wParam) == CBN_SELCHANGE)
{
ChangeMapFont();
}
break;
default:
// We didn't handle it
RetCode = -1;
@ -504,4 +513,26 @@ CCharMapWindow::CreateFontComboBox()
0);
return (ret == 1);
}
}
bool
CCharMapWindow::ChangeMapFont(
)
{
HWND hCombo;
hCombo = GetDlgItem(m_hMainWnd, IDC_FONTCOMBO);
INT Length;
Length = GetWindowTextLengthW(hCombo);
if (!Length) return false;
CAtlStringW FontName;// = L"hahaha";
FontName.Preallocate(Length);
SendMessageW(hCombo,
WM_GETTEXT,
FontName.GetAllocLength(),
(LPARAM)FontName.GetBuffer());
return m_GridView->SetFont(FontName);
}

View file

@ -78,4 +78,7 @@ private:
bool CreateFontComboBox(
);
bool ChangeMapFont(
);
};

View file

@ -1,6 +1,6 @@
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
IDD_CHARMAP DIALOGEX 6, 6, 292, 224
IDD_CHARMAP DIALOGEX 6, 6, 290, 224
FONT 8, "MS Shell Dlg", 0, 0
STYLE WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX
CAPTION "ReactOS Character Map"
@ -13,17 +13,6 @@ BEGIN
WS_CHILD | WS_VISIBLE | WS_TABSTOP, 74, 186, 114, 13
DEFPUSHBUTTON "Select", IDC_SELECT, 194, 186, 44, 13
PUSHBUTTON "Copy", IDC_COPY, 242, 186, 44, 13, WS_DISABLED
//CONTROL "Advanced view", IDC_CHECK_ADVANCED, "Button", BS_AUTOCHECKBOX |
// WS_TABSTOP, 8, 208, 95, 10
//LTEXT "Charset:", IDC_STATIC, 8, 8, 48, 8
//COMBOBOX IDC_COMBO_CHARSET, 72, 4, 116, 80, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
//LTEXT "Group by:", IDC_STATIC, 8, 28, 50, 8
//COMBOBOX IDC_COMBO_GROUPBY, 72, 24, 116, 80, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
//PUSHBUTTON "Search", IDC_BUTTON_SEARCH, 200, 44, 50, 14
//EDITTEXT IDC_EDIT_SEARCH, 72, 44, 116, 14, ES_AUTOHSCROLL
//LTEXT "Search for:", IDC_STATIC, 8, 48, 42, 8
//LTEXT "Unicode:", IDC_STATIC, 200, 8, 30, 8
//EDITTEXT IDC_EDIT_UNICODE, 236, 4, 28, 12, ES_AUTOHSCROLL
END
STRINGTABLE