Menu

Scrolling / Fixed Font - Help

2002-12-04
2012-09-26
  • Nobody/Anonymous

    TThis is a program written while I am working through Petzolds Programming Windows, based on programs in that book.

    It allows you to scroll around a number of permuted alphabetical strings, with the mouse and keyboard.

    The problem is that, although it works fine with the default font, when I switch to SYSTEM_FIXED_FONT, the vertical scrolling goes all to hell.

    If I force a full repaint, e.g. by minimizing and restoring the window, the output is displayed correctly.

    It appears that only downward scrolling is affected, upward and all horizontal scrolling is fine.

    Does anyone have any ideas?

    I have Windows XP.

    Derek

    #include <string>
    #include <vector>
    #include <windows.h>

    vector<string>v;
    int maxstrlen = 26;

    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);

    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE PrevhInstance, PSTR
                        szCmdLIne , int iCmdShow)
    {
        for(int i=0; i<27; ++i)
        {
            string s;
            for(int j  = 0; j< 26; ++j)
            {
                int c = j + i;
                if (c > 25)
                {
                    c -= 26;
                }
                s = s + char(c+97);
            };
            v.push_back(s);
        }
       
        static TCHAR szAppName[] = TEXT ("Hello Win");
        HWND hwnd;
        MSG msg;
        WNDCLASS wndclass;
       
        wndclass.style          = CS_HREDRAW | CS_VREDRAW;
        wndclass.lpfnWndProc    = WndProc;
        wndclass.cbClsExtra     = 0;
        wndclass.cbWndExtra     = 0;
        wndclass.hInstance      = hInstance;
        wndclass.hIcon          = LoadIcon (NULL, IDI_APPLICATION);
        wndclass.hCursor        = LoadCursor (NULL, IDC_ARROW);
        wndclass.hbrBackground  = (HBRUSH) GetStockObject (WHITE_BRUSH);
        wndclass.lpszMenuName   = NULL;
        wndclass.lpszClassName  = szAppName;

        if(!RegisterClass (&wndclass))
        {
            MessageBox (NULL, TEXT ("This program requires Windows NT!"),
                        szAppName, MB_ICONERROR);
            return  0;
        }

        hwnd = CreateWindow (szAppName,
                             TEXT ("The Keys Program"),
                             WS_OVERLAPPEDWINDOW | WS_VSCROLL | WS_HSCROLL,
                             (1024 - 200) / 2,
                             (768 - 200) / 2,
                             200,
                             200,
                             NULL,
                             NULL,
                             hInstance,
                             NULL);

        ShowWindow (hwnd, iCmdShow);
        UpdateWindow (hwnd);

        while (GetMessage (&msg, NULL, 0, 0))
        {
            TranslateMessage (&msg);
            DispatchMessage (&msg);
        }
        return msg.wParam;
    }

    LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        HDC         hdc;
        PAINTSTRUCT ps;
        RECT        rect;
        SCROLLINFO  si;
        int         iVertPos;
        int         iHorzPos;
        static int  cxClient;
        static int  cyClient;
        int         iPaintBeg;
        int         iPaintEnd;
                   
        switch (message)
        {
            case WM_CREATE:
                   
                    hdc = GetDC(hwnd);
                   
                    SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
                   
                    TEXTMETRIC tm;
                    GetTextMetrics(hdc, &tm);
                            static int cyChar = tm.tmHeight + tm.tmExternalLeading;
                            static int cxChar = tm.tmAveCharWidth;
                    ReleaseDC(hwnd, hdc);

                   
                    return 0;
           
            case WM_PAINT:
                    hdc = BeginPaint (hwnd, &ps);

                    SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
                   
                    si.cbSize = sizeof(si);
                    si.fMask = SIF_POS;
                    GetScrollInfo(hwnd, SB_VERT, &si);
                    iVertPos = si.nPos;
                    GetScrollInfo(hwnd, SB_HORZ, &si);
                    iHorzPos = si.nPos;

                    iPaintBeg = max(0, iVertPos + ps.rcPaint.top / cyChar);
                    iPaintEnd = min(v.size()-1, iVertPos + ps.rcPaint.bottom / cyChar);

                    for(int i= iPaintBeg; i< iPaintEnd; ++i)
                    {
                        int x = cxChar * (1 - iHorzPos);
                        int y = cyChar * (i - iVertPos);
                        const char* p = v[i].c_str();
                        int lenp = v[i].length();
                        TextOut(hdc, x, y,
                                p, lenp);
                    }
                   
                    EndPaint (hwnd, &ps);
                    return 0;

            case WM_SIZE:
                    cxClient = LOWORD(lParam);
                    cyClient = HIWORD(lParam);
           
                    si.cbSize = sizeof(SCROLLINFO);
                    si.fMask = SIF_RANGE | SIF_PAGE;
                    si.nMin = 0;
                    si.nMax = v.size()- 1;
                    si.nPage = cyClient / cyChar;
                    SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
                   
                    si.cbSize = sizeof(SCROLLINFO);
                    si.fMask = SIF_RANGE | SIF_PAGE;
                    si.nMin = 0;
                    si.nMax = maxstrlen;
                    si.nPage = cxClient / cxChar;
                    SetScrollInfo(hwnd, SB_HORZ, &si, TRUE);

                    return 0;
           
            case WM_VSCROLL:
                   
                    si.cbSize = sizeof(si);
                    si.fMask = SIF_ALL;
                    GetScrollInfo(hwnd, SB_VERT, &si);
                    iVertPos = si.nPos;
                   
                    switch(LOWORD(wParam)) 
                    {
                        case SB_TOP:
                            si.nPos = si.nMin;
                            break;
                           
                        case SB_BOTTOM:
                            si.nPos = si.nMax;
                            break;
                       
                        case SB_LINEUP:
                            --si.nPos;
                            break;

                        case SB_LINEDOWN:
                            ++si.nPos;
                            break;
                       
                        case SB_PAGEUP:
                            si.nPos -= si.nPage;
                            break;
       
                        case SB_PAGEDOWN:
                            si.nPos += si.nPage;
                            break;
                       
                        case SB_THUMBTRACK:
                            si.nPos = si.nTrackPos;
                            break;
                    }
           
                    si.fMask = SIF_POS;
                    SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
                    GetScrollInfo(hwnd, SB_VERT, &si);

                    if(si.nPos != iVertPos)
                    {
                        ScrollWindow(hwnd, 0, cyChar * (iVertPos - si.nPos),
                                     NULL, NULL);
                        UpdateWindow(hwnd);
                    }
                    return 0;

            case WM_HSCROLL:
                   
                    si.cbSize = sizeof(si);
                    si.fMask = SIF_ALL;
                    GetScrollInfo(hwnd, SB_HORZ, &si);
                    iHorzPos = si.nPos;

                    switch(LOWORD(wParam)) 
                    {
                        case SB_LINELEFT:
                            --si.nPos;
                            break;

                        case SB_LINERIGHT:
                            ++si.nPos;
                            break;
                       
                        case SB_PAGELEFT:
                            si.nPos -= si.nPage;
                            break;
       
                        case SB_PAGERIGHT:
                            si.nPos += si.nPage;
                            break;
                       
                        case SB_THUMBTRACK:
                            si.nPos = si.nTrackPos;
                            break;
                    }
           
                    si.fMask = SIF_POS;
                    SetScrollInfo(hwnd, SB_HORZ, &si, TRUE);
                    GetScrollInfo(hwnd, SB_HORZ, &si);

                    if(si.nPos != iHorzPos)
                    {
                        ScrollWindow(hwnd, cxChar * (iHorzPos - si.nPos), 0, NULL,
                                     NULL);
                        UpdateWindow(hwnd);
                    }
                    return 0;
       
        case WM_KEYDOWN:
                    switch(wParam)
                    {
                        case VK_HOME:
                            SendMessage(hwnd, WM_VSCROLL, SB_TOP, 0);
                            break;
                       
                        case VK_END:
                            SendMessage(hwnd, WM_VSCROLL, SB_BOTTOM, 0);
                            break;
                       
                        case VK_PRIOR:
                            SendMessage(hwnd, WM_VSCROLL, SB_PAGEUP, 0);
                            break;
                           
                        case VK_NEXT:
                            SendMessage(hwnd, WM_VSCROLL, SB_PAGEDOWN, 0);
                            break;
                       
                        case VK_UP:
                            SendMessage(hwnd, WM_VSCROLL, SB_LINEUP, 0);
                            break;
                   
                        case VK_DOWN:
                            SendMessage(hwnd, WM_VSCROLL, SB_LINEDOWN, 0);
                            break;
                           
                        case VK_LEFT:
                            SendMessage(hwnd, WM_HSCROLL, SB_LINELEFT, 0);
                            break;
                           
                        case VK_RIGHT:
                            SendMessage(hwnd, WM_HSCROLL, SB_LINERIGHT, 0);
                            break;
                    }                       
                    return 0;
                   
        case WM_DESTROY:
                    PostQuitMessage(0);
                    return 0;
        }
        return DefWindowProc (hwnd, message, wParam, lParam);
    }

    his is a program written while I am working through Petzolds Programming Windows, based on programs in that book.

    It allows you to scroll around a number of permuted alphabetical strings, with the mouse and keyboard.

    The problem is that, although it works fine with the default font, when I switch to SYSTEM_FIXED_FONT, the vertical scrolling goes all to hell.

    If I force a full repaint, e.g. by minimizing and restoring the window, the output is displayed correctly.

    Does anyone have any ideas?

    Derek

    #include <string>
    #include <vector>
    #include <windows.h>

    vector<string>v;
    int maxstrlen = 26;

    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);

    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE PrevhInstance, PSTR
                        szCmdLIne , int iCmdShow)
    {
        for(int i=0; i<27; ++i)
        {
            string s;
            for(int j  = 0; j< 26; ++j)
            {
                int c = j + i;
                if (c > 25)
                {
                    c -= 26;
                }
                s = s + char(c+97);
            };
            v.push_back(s);
        }
       
        static TCHAR szAppName[] = TEXT ("Hello Win");
        HWND hwnd;
        MSG msg;
        WNDCLASS wndclass;
       
        wndclass.style          = CS_HREDRAW | CS_VREDRAW;
        wndclass.lpfnWndProc    = WndProc;
        wndclass.cbClsExtra     = 0;
        wndclass.cbWndExtra     = 0;
        wndclass.hInstance      = hInstance;
        wndclass.hIcon          = LoadIcon (NULL, IDI_APPLICATION);
        wndclass.hCursor        = LoadCursor (NULL, IDC_ARROW);
        wndclass.hbrBackground  = (HBRUSH) GetStockObject (WHITE_BRUSH);
        wndclass.lpszMenuName   = NULL;
        wndclass.lpszClassName  = szAppName;

        if(!RegisterClass (&wndclass))
        {
            MessageBox (NULL, TEXT ("This program requires Windows NT!"),
                        szAppName, MB_ICONERROR);
            return  0;
        }

        hwnd = CreateWindow (szAppName,
                             TEXT ("The Keys Program"),
                             WS_OVERLAPPEDWINDOW | WS_VSCROLL | WS_HSCROLL,
                             (1024 - 200) / 2,
                             (768 - 200) / 2,
                             200,
                             200,
                             NULL,
                             NULL,
                             hInstance,
                             NULL);

        ShowWindow (hwnd, iCmdShow);
        UpdateWindow (hwnd);

        while (GetMessage (&msg, NULL, 0, 0))
        {
            TranslateMessage (&msg);
            DispatchMessage (&msg);
        }
        return msg.wParam;
    }

    LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        HDC         hdc;
        PAINTSTRUCT ps;
        RECT        rect;
        SCROLLINFO  si;
        int         iVertPos;
        int         iHorzPos;
        static int  cxClient;
        static int  cyClient;
        int         iPaintBeg;
        int         iPaintEnd;
                   
        switch (message)
        {
            case WM_CREATE:
                   
                    hdc = GetDC(hwnd);
                   
                    SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
                   
                    TEXTMETRIC tm;
                    GetTextMetrics(hdc, &tm);
                            static int cyChar = tm.tmHeight + tm.tmExternalLeading;
                            static int cxChar = tm.tmAveCharWidth;
                    ReleaseDC(hwnd, hdc);

                   
                    return 0;
           
            case WM_PAINT:
                    hdc = BeginPaint (hwnd, &ps);

                    SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
                   
                    si.cbSize = sizeof(si);
                    si.fMask = SIF_POS;
                    GetScrollInfo(hwnd, SB_VERT, &si);
                    iVertPos = si.nPos;
                    GetScrollInfo(hwnd, SB_HORZ, &si);
                    iHorzPos = si.nPos;

                    iPaintBeg = max(0, iVertPos + ps.rcPaint.top / cyChar);
                    iPaintEnd = min(v.size()-1, iVertPos + ps.rcPaint.bottom / cyChar);

                    for(int i= iPaintBeg; i< iPaintEnd; ++i)
                    {
                        int x = cxChar * (1 - iHorzPos);
                        int y = cyChar * (i - iVertPos);
                        const char* p = v[i].c_str();
                        int lenp = v[i].length();
                        TextOut(hdc, x, y,
                                p, lenp);
                    }
                   
                    EndPaint (hwnd, &ps);
                    return 0;

            case WM_SIZE:
                    cxClient = LOWORD(lParam);
                    cyClient = HIWORD(lParam);
           
                    si.cbSize = sizeof(SCROLLINFO);
                    si.fMask = SIF_RANGE | SIF_PAGE;
                    si.nMin = 0;
                    si.nMax = v.size()- 1;
                    si.nPage = cyClient / cyChar;
                    SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
                   
                    si.cbSize = sizeof(SCROLLINFO);
                    si.fMask = SIF_RANGE | SIF_PAGE;
                    si.nMin = 0;
                    si.nMax = maxstrlen;
                    si.nPage = cxClient / cxChar;
                    SetScrollInfo(hwnd, SB_HORZ, &si, TRUE);

                    return 0;
           
            case WM_VSCROLL:
                   
                    si.cbSize = sizeof(si);
                    si.fMask = SIF_ALL;
                    GetScrollInfo(hwnd, SB_VERT, &si);
                    iVertPos = si.nPos;
                   
                    switch(LOWORD(wParam)) 
                    {
                        case SB_TOP:
                            si.nPos = si.nMin;
                            break;
                           
                        case SB_BOTTOM:
                            si.nPos = si.nMax;
                            break;
                       
                        case SB_LINEUP:
                            --si.nPos;
                            break;

                        case SB_LINEDOWN:
                            ++si.nPos;
                            break;
                       
                        case SB_PAGEUP:
                            si.nPos -= si.nPage;
                            break;
       
                        case SB_PAGEDOWN:
                            si.nPos += si.nPage;
                            break;
                       
                        case SB_THUMBTRACK:
                            si.nPos = si.nTrackPos;
                            break;
                    }
           
                    si.fMask = SIF_POS;
                    SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
                    GetScrollInfo(hwnd, SB_VERT, &si);

                    if(si.nPos != iVertPos)
                    {
                        ScrollWindow(hwnd, 0, cyChar * (iVertPos - si.nPos),
                                     NULL, NULL);
                        UpdateWindow(hwnd);
                    }
                    return 0;

            case WM_HSCROLL:
                   
                    si.cbSize = sizeof(si);
                    si.fMask = SIF_ALL;
                    GetScrollInfo(hwnd, SB_HORZ, &si);
                    iHorzPos = si.nPos;

                    switch(LOWORD(wParam)) 
                    {
                        case SB_LINELEFT:
                            --si.nPos;
                            break;

                        case SB_LINERIGHT:
                            ++si.nPos;
                            break;
                       
                        case SB_PAGELEFT:
                            si.nPos -= si.nPage;
                            break;
       
                        case SB_PAGERIGHT:
                            si.nPos += si.nPage;
                            break;
                       
                        case SB_THUMBTRACK:
                            si.nPos = si.nTrackPos;
                            break;
                    }
           
                    si.fMask = SIF_POS;
                    SetScrollInfo(hwnd, SB_HORZ, &si, TRUE);
                    GetScrollInfo(hwnd, SB_HORZ, &si);

                    if(si.nPos != iHorzPos)
                    {
                        ScrollWindow(hwnd, cxChar * (iHorzPos - si.nPos), 0, NULL,
                                     NULL);
                        UpdateWindow(hwnd);
                    }
                    return 0;
       
        case WM_KEYDOWN:
                    switch(wParam)
                    {
                        case VK_HOME:
                            SendMessage(hwnd, WM_VSCROLL, SB_TOP, 0);
                            break;
                       
                        case VK_END:
                            SendMessage(hwnd, WM_VSCROLL, SB_BOTTOM, 0);
                            break;
                       
                        case VK_PRIOR:
                            SendMessage(hwnd, WM_VSCROLL, SB_PAGEUP, 0);
                            break;
                           
                        case VK_NEXT:
                            SendMessage(hwnd, WM_VSCROLL, SB_PAGEDOWN, 0);
                            break;
                       
                        case VK_UP:
                            SendMessage(hwnd, WM_VSCROLL, SB_LINEUP, 0);
                            break;
                   
                        case VK_DOWN:
                            SendMessage(hwnd, WM_VSCROLL, SB_LINEDOWN, 0);
                            break;
                           
                        case VK_LEFT:
                            SendMessage(hwnd, WM_HSCROLL, SB_LINELEFT, 0);
                            break;
                           
                        case VK_RIGHT:
                            SendMessage(hwnd, WM_HSCROLL, SB_LINERIGHT, 0);
                            break;
                    }                       
                    return 0;
                   
        case WM_DESTROY:
                    PostQuitMessage(0);
                    return 0;
        }
        return DefWindowProc (hwnd, message, wParam, lParam);
    }

     
    • Nobody/Anonymous

      Have discovered it is not a problem going from default font to SYSTEM_FIXED_FONT, but with any font other than the default font.

      Some problem getting the size of the new font?

      Derek

       
    • Nobody/Anonymous

      Have discovered that some sizes of window do not have problem.

      Derek

       
    • Nobody/Anonymous

      One of the sizes that does not show proyblem is y = 140 pixels.

      Derek

       
    • Nobody/Anonymous

      Further information:

      if I change THUMBTRACK to THUMBPOSITION, vertical scrolling also works.

      Not sure if any one's reading this!
      Think I'll just consider the forum my own private notepad.

      Derek

       
    • Nobody/Anonymous

      In case anyone's interested I found the problem:

      a missing = in the code I'd modelled mine on!

      Derek

       

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.