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

View file

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

View file

@ -21,7 +21,8 @@ extern HINSTANCE g_hInstance;
CGridView::CGridView() : CGridView::CGridView() :
m_xNumCells(20), m_xNumCells(20),
m_yNumCells(10) m_yNumCells(10),
ScrollPosition(0)
{ {
m_szMapWndClass = L"CharGridWClass"; m_szMapWndClass = L"CharGridWClass";
} }
@ -62,7 +63,94 @@ CGridView::Create(
} }
bool 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 // Go through all the cells and calculate
@ -71,10 +159,10 @@ CGridView::UpdateGridLayout(
for (int x = 0; x < m_xNumCells; x++) for (int x = 0; x < m_xNumCells; x++)
{ {
RECT CellCoordinates; RECT CellCoordinates;
CellCoordinates.left = x * m_CellSize.cx + 1; CellCoordinates.left = x * m_CellSize.cx;
CellCoordinates.top = y * m_CellSize.cy + 1; CellCoordinates.top = y * m_CellSize.cy;
CellCoordinates.right = (x + 1) * m_CellSize.cx + 2; CellCoordinates.right = (x + 1) * m_CellSize.cx + 1;
CellCoordinates.bottom = (y + 1) * m_CellSize.cy + 2; CellCoordinates.bottom = (y + 1) * m_CellSize.cy + 1;
m_Cells[y][x]->SetCellCoordinates(CellCoordinates); m_Cells[y][x]->SetCellCoordinates(CellCoordinates);
} }
@ -125,6 +213,7 @@ CGridView::OnSize(
m_ClientCoordinates.right = ParentRect.right - m_ClientCoordinates.left - 10; m_ClientCoordinates.right = ParentRect.right - m_ClientCoordinates.left - 10;
m_ClientCoordinates.bottom = ParentRect.bottom - m_ClientCoordinates.top - 70; m_ClientCoordinates.bottom = ParentRect.bottom - m_ClientCoordinates.top - 70;
// Resize the grid window
SetWindowPos(m_hwnd, SetWindowPos(m_hwnd,
NULL, NULL,
m_ClientCoordinates.left, m_ClientCoordinates.left,
@ -133,20 +222,92 @@ CGridView::OnSize(
m_ClientCoordinates.bottom, m_ClientCoordinates.bottom,
SWP_NOZORDER | SWP_SHOWWINDOW); SWP_NOZORDER | SWP_SHOWWINDOW);
// Get the client area we can draw on. The position we set above // Get the client area we can draw on. The position we set above includes
// includes a scrollbar. GetClientRect gives us the size without // a scrollbar which we obvioulsy can't draw on. GetClientRect gives us
// the scroll, and it more efficient than getting the scroll // the size without the scroll, and it more efficient than getting the
// metrics and calculating the size // scroll metrics and calculating the size from that
RECT ClientRect; RECT ClientRect;
GetClientRect(m_hwnd, &ClientRect); GetClientRect(m_hwnd, &ClientRect);
m_CellSize.cx = ClientRect.right / m_xNumCells; m_CellSize.cx = ClientRect.right / m_xNumCells;
m_CellSize.cy = ClientRect.bottom / m_yNumCells; m_CellSize.cy = ClientRect.bottom / m_yNumCells;
UpdateGridLayout(); // Let all the cells know about their new coords
UpdateCellCoordinates();
return 0; 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 LRESULT
CGridView::OnPaint( CGridView::OnPaint(
_In_opt_ HDC hdc _In_opt_ HDC hdc
@ -176,8 +337,10 @@ CGridView::OnPaint(
} }
} }
// Make sure we have a valid DC
if (bSuccess) if (bSuccess)
{ {
// Paint the grid and chars
DrawGrid(&PaintStruct); DrawGrid(&PaintStruct);
if (LocalHdc) if (LocalHdc)
@ -237,6 +400,16 @@ CGridView::MapWndProc(
break; break;
} }
case WM_VSCROLL:
{
INT Value, Pos;
Value = LOWORD(wParam);
Pos = HIWORD(wParam);
This->OnVScroll(Value, Pos);
break;
}
case WM_PAINT: case WM_PAINT:
{ {
This->OnPaint((HDC)wParam); This->OnPaint((HDC)wParam);
@ -266,12 +439,29 @@ CGridView::DrawGrid(
_In_ LPPAINTSTRUCT PaintStruct _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 // Traverse all the cells and tell them to paint themselves
for (int y = 0; y < m_yNumCells; y++) for (int y = 0; y < m_yNumCells; y++)
for (int x = 0; x < m_xNumCells; x++) 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); m_Cells[y][x]->OnPaint(*PaintStruct);
i++;
} }
SelectObject(PaintStruct->hdc, hOldFont);
} }
void void

View file

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

View file

@ -199,6 +199,8 @@ CCharMapWindow::OnCreate(_In_ HWND hDlg)
if (!CreateFontComboBox()) if (!CreateFontComboBox())
return FALSE; return FALSE;
ChangeMapFont();
// Configure Richedit control for sending notification changes. // Configure Richedit control for sending notification changes.
DWORD evMask; DWORD evMask;
evMask = SendDlgItemMessage(hDlg, IDC_TEXTBOX, EM_GETEVENTMASK, 0, 0); evMask = SendDlgItemMessage(hDlg, IDC_TEXTBOX, EM_GETEVENTMASK, 0, 0);
@ -283,6 +285,13 @@ CCharMapWindow::OnCommand(_In_ WPARAM wParam,
case IDC_CHECK_ADVANCED: case IDC_CHECK_ADVANCED:
break; break;
case IDC_FONTCOMBO:
if (HIWORD(wParam) == CBN_SELCHANGE)
{
ChangeMapFont();
}
break;
default: default:
// We didn't handle it // We didn't handle it
RetCode = -1; RetCode = -1;
@ -505,3 +514,25 @@ CCharMapWindow::CreateFontComboBox()
return (ret == 1); 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 CreateFontComboBox(
); );
bool ChangeMapFont(
);
}; };

View file

@ -1,6 +1,6 @@
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US 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 FONT 8, "MS Shell Dlg", 0, 0
STYLE WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX STYLE WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX
CAPTION "ReactOS Character Map" CAPTION "ReactOS Character Map"
@ -13,17 +13,6 @@ BEGIN
WS_CHILD | WS_VISIBLE | WS_TABSTOP, 74, 186, 114, 13 WS_CHILD | WS_VISIBLE | WS_TABSTOP, 74, 186, 114, 13
DEFPUSHBUTTON "Select", IDC_SELECT, 194, 186, 44, 13 DEFPUSHBUTTON "Select", IDC_SELECT, 194, 186, 44, 13
PUSHBUTTON "Copy", IDC_COPY, 242, 186, 44, 13, WS_DISABLED 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 END
STRINGTABLE STRINGTABLE