[CHARMAP_NEW]
authorGed Murphy <gedmurphy@reactos.org>
Tue, 24 Nov 2015 17:55:27 +0000 (17:55 +0000)
committerGed Murphy <gedmurphy@reactos.org>
Tue, 24 Nov 2015 17:55:27 +0000 (17:55 +0000)
- 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

reactos/base/applications/charmap_new/Cell.cpp
reactos/base/applications/charmap_new/Cell.h
reactos/base/applications/charmap_new/GridView.cpp
reactos/base/applications/charmap_new/GridView.h
reactos/base/applications/charmap_new/MainWindow.cpp
reactos/base/applications/charmap_new/MainWindow.h
reactos/base/applications/charmap_new/lang/en-US.rc

index 7eacc89..fba4bcd 100644 (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
index 406dddf..ea1a72d 100644 (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
index 8dbf8b4..9d96423 100644 (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
index acc2615..ede8029 100644 (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(
index 82f0796..6bf1be8 100644 (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);
-}
\ No newline at end of file
+}
+
+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);
+}
index 72a0290..63127d7 100644 (file)
@@ -78,4 +78,7 @@ private:
 
     bool CreateFontComboBox(
         );
+
+    bool ChangeMapFont(
+        );
 };
\ No newline at end of file
index f0106ec..a7493c8 100644 (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