1

In print preview dialog, I would like to enable page change via mouse wheeling. As I am still a beginner for MFC programming, I don't have code to start with. The closest question I've found is this one (for C#) but no clear answer yet: https://www.codeproject.com/Questions/555242/5bc-23-5dplusprintpreviewdialogplusandplusmousewhe.

user180574
  • 5,681
  • 13
  • 53
  • 94
  • [Printing and Print Preview](https://learn.microsoft.com/en-us/cpp/mfc/printing-and-print-preview) provides documentation as well as an overview of the [Print Preview Architecture](https://learn.microsoft.com/en-us/cpp/mfc/print-preview-architecture). – IInspectable Apr 13 '20 at 18:23

2 Answers2

2

If you are using MFC's CPreviewView class, then you can derive a custom class from that, in which you can override the OnMouseWheel member. In your override, you would call the OnVScroll handler to shift up or down, as though you had clicked on the up/down arrows of the scrollbar:

BOOL MyPreviewView::OnMouseWheel(UINT /*flags*/, short delta, CPoint /*point*/)
{
    OnVScroll(UINT((delta < 0) ? SB_LINEDOWN : SB_LINEUP), 0, nullptr);
    return TRUE;
}

Also, you need to add ON_WM_MOUSEWHEEL() to your derived class' message-map:

BEGIN_MESSAGE_MAP(MyPreviewView, CPreviewView)
    //...
    ON_WM_MOUSEWHEEL()
    //...
END_MESSAGE_MAP()

Feel free to ask for further clarification and/or explanation.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
  • Thank you! It works great but may I ask for a few refinements: (a) How to advance one page at a time? Right now, using your code each wheeling tick will advance several pages (in my case around 30 pages), and (b) I don't seem to be able to roll back to the first page. When I roll back to around 30th page, then roll back one more tick brings me to the last page?? – user180574 Apr 13 '20 at 20:51
  • @user180574 Maybe try using `SB_LINEDOWN` and `SB_LINEUP` for a finer scroll. This may be *too* fine, in which case you'd have to make multiple calls to `OnVScroll`. More info [here](https://learn.microsoft.com/en-us/cpp/mfc/reference/cwnd-class?view=vs-2019#onvscroll). – Adrian Mole Apr 13 '20 at 20:57
  • @user180574 And, please, if the `LINE_` versions work, let me know so that I can edit my answer accordingly. – Adrian Mole Apr 13 '20 at 20:58
  • @user180574 Let's tackle (a) first - if we get that sorted, we can tackle (b). – Adrian Mole Apr 13 '20 at 21:00
  • @user180574 The `PAGE` and `LINE` terminology is confusing - `SB_LINEUP` is for a click in on the up arrow at the end of a scrollbar, whereas `SB_PAGEUP` is for a click in the bar itself, between the dragger and the end of the bar. The actual page amounts for the latter will probably vary with the overall size of the document (# pages). – Adrian Mole Apr 13 '20 at 21:13
  • Yes, ```SB_LINEDOWN``` and ```SB_LINEUP``` work great and (b) is solved as well! Thank you for the help! – user180574 Apr 13 '20 at 21:30
  • @user180574 Good! And thanks for the feedback - I have edited my answer accordingly. – Adrian Mole Apr 13 '20 at 21:33
0

It is an addition to the existing answer of Adrian Mole's Answer

If you are not using custom class already, this is the complete implementation of the class:

MyPreviewViewEx.h

// CMyPreviewViewEx view

class CMyPreviewViewEx : public CPreviewViewEx
{
    DECLARE_DYNCREATE(CMyPreviewViewEx)

protected:
    CMyPreviewViewEx()              {}           // protected constructor used by dynamic creation
    virtual ~CMyPreviewViewEx()     {}

    DECLARE_MESSAGE_MAP()
public:
    afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
    static void MyPrintPreview(CView* pView);
};

MyPreviewViewEx.cpp

// CMyPreviewViewEx
IMPLEMENT_DYNCREATE(CMyPreviewViewEx, CPreviewViewEx)

BEGIN_MESSAGE_MAP(CMyPreviewViewEx, CPreviewViewEx)
    ON_WM_MOUSEWHEEL()
END_MESSAGE_MAP()


// CMyPreviewViewEx message handlers

BOOL CMyPreviewViewEx::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
    OnVScroll(UINT((zDelta < 0) ? SB_LINEDOWN : SB_LINEUP), 0, nullptr);
    return TRUE;
}

// Override AFXPrintPreview
void CMyPreviewViewEx::MyPrintPreview(CView* pView)
{
    ASSERT_VALID(pView);

    CPrintPreviewState *pState= new CPrintPreviewState;

    if (!pView->DoPrintPreview(IDD_AFXBAR_RES_PRINT_PREVIEW, pView, RUNTIME_CLASS(CMyPreviewViewEx), pState))
    {
        TRACE0("Error: OnFilePrintPreview failed.\n");
        AfxMessageBox(AFX_IDP_COMMAND_FAILURE);
        delete pState;      // preview failed to initialize, delete State now
    }
}

In the view class, change as applicable

// AFXPrintPreview(pView);
CMyPreviewViewEx::MyPrintPreview(pView);
Harsh Shankar
  • 506
  • 5
  • 16