Using PDFView in a Non-MFC Windows application [PDFNet for C++, Windows]

Q:

We need to integrate your PDF viewer (pdftron.PDF.PDFView) into a Non-
MFC Windows application. The PDFView sample is using MFC. Is it
possible to integrate PDFView class in a Non-MFC Windows application?
----

A:
Since you are developing in native code, I assume that you are using
PDFNet SDK for C++ (instead of PDFNet SDK for .NET).

The current PDFView sample project (http://www.pdftron.com/net/
samplecode.html#PDFView) is using MFC, however this is not the
limitation of the SDK. So you should be able to use the same API in
Win32, MFC, ATL, or with any other API framework.

Although the SDK comes only with a MFC version of PDFView sample
project, it should be straightforward to map the code to Win32 C or
ATL application. For example, your Win32 message pump may look as
follow:

BOOL CALLBACK WndProc(HWND hwnd, UINT wMsg, WPARAM wparam, LPARAM
lparam) {

switch (wMsg)
{
// case WM_INITDIALOG: create & initialize PDFView?
// (similar to OnInitialUpdate() in MFC sample)
// ...
// break;

case WM_PAINT:
  {
    PAINTSTRUCT ps;
    HDC hdc = BeginPaint(hwnd, &ps);
    const char* buf = mp_imp->GetBuffer();
    if (hdc && buf)
    {
      BITMAPINFO bmp;
      bmp.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
      bmp.bmiHeader.biWidth = _width;
      bmp.bmiHeader.biHeight = -_height;
      bmp.bmiHeader.biPlanes = 1;
      bmp.bmiHeader.biBitCount = 32; // For BGRA format
      bmp.bmiHeader.biCompression = 0;
      bmp.bmiHeader.biSizeImage = _height * _stride;
      bmp.bmiHeader.biXPelsPerMeter = 0;
      bmp.bmiHeader.biYPelsPerMeter = 0;
      bmp.bmiHeader.biClrUsed = 0;
      bmp.bmiHeader.biClrImportant = 0;

      ::SetDIBitsToDevice(hdc,
        0, 0,
        _width, _height,
        0, 0, 0,
        _height,
        buf,
        &bmp,
        DIB_RGB_COLORS);
    }
    EndPaint(hwnd, &ps);
    m->Result = 0; // An application returns zero if it processes this
message.
  }
  return;
case WM_SIZE:
  {
    int xNewSize = LOWORD(lparam);
    int yNewSize = HIWORD(lparam);

    int comps = 4;
    _width = this->ClientSize.get_Width();
    _height = this->ClientSize.get_Height();
    _stride = ((_width * comps + 3) / 4) * 4;
    mp_imp->OnSize(_width, _height, _stride);
    m->Result = 0; // If an application processes this message, it
should return zero.
  }
    break;
case WM_ERASEBKGND:
  {
    // Don't erase background
    m->Result = 1; // return nonzero if application erases the
background
    return;
  }
case WM_HSCROLL:
  {
    SCROLLINFO scrollinfo; // Get the vertical scroll bar information
    scrollinfo.cbSize = sizeof(SCROLLINFO);
    scrollinfo.fMask = SIF_TRACKPOS | SIF_PAGE;
    GetScrollInfo(hwnd, SB_HORZ, &scrollinfo);

    switch (LOWORD(wparam))
    {
    case SB_LINELEFT: // user clicked left arrow
      mp_imp->OnScroll(-_scroll_pix_inc, 0);
      break;
    case SB_LINERIGHT: // user clicked right arrow
      mp_imp->OnScroll(_scroll_pix_inc, 0);
      break;
    case SB_PAGELEFT: // user clicked the scroll bar shaft left of the
scroll box
      mp_imp->OnScroll(-int(scrollinfo.nPage), 0);
      break;
    case SB_PAGERIGHT: // user clicked the scroll bar shaft right of the
scroll box
        mp_imp->OnScroll(scrollinfo.nPage, 0);
      break;
    case SB_THUMBTRACK: // user dragged the scroll box
    case SB_THUMBPOSITION:
      mp_imp->SetHScrollPos(scrollinfo.nTrackPos);
      break;
    default:
      break;
    }

    scrollinfo.nPos = int(mp_imp->GetHScrollPos());
    scrollinfo.cbSize = sizeof(SCROLLINFO);
    scrollinfo.fMask = SIF_POS;
    SetScrollInfo(hwnd, SB_HORZ, &scrollinfo, TRUE);

    m->Result = 0;
  }
  return;
case WM_VSCROLL:
  {
    SCROLLINFO scrollinfo; // Get the vertical scroll bar information
    scrollinfo.cbSize = sizeof(SCROLLINFO);
    scrollinfo.fMask = SIF_TRACKPOS | SIF_PAGE;
    GetScrollInfo(hwnd, SB_VERT, &scrollinfo);

    switch (LOWORD(wparam))
    {
    case SB_TOP: // user clicked the HOME keyboard key
      break;
    case SB_BOTTOM: // user clicked the END keyboard key
      break;
    case SB_LINEUP: // user clicked the top arrow
      mp_imp->OnScroll(0, -_scroll_pix_inc);
      break;
    case SB_LINEDOWN: // user clicked the bottom arrow
      mp_imp->OnScroll(0, _scroll_pix_inc);
      break;
    case SB_PAGEUP: // user clicked the scroll bar shaft above the
scroll box
      mp_imp->OnScroll(0, -int(scrollinfo.nPage));
      break;
    case SB_PAGEDOWN: // user clicked the scroll bar shaft below the
scroll box
      mp_imp->OnScroll(0, scrollinfo.nPage);
      break;
    case SB_THUMBTRACK: // user dragged the scroll box
    case SB_THUMBPOSITION:
      mp_imp->SetVScrollPos(scrollinfo.nTrackPos);
      break;
    default:
      break;
    }

    scrollinfo.nPos = int(mp_imp->GetVScrollPos());
    scrollinfo.cbSize = sizeof(SCROLLINFO);
    scrollinfo.fMask = SIF_POS;
    SetScrollInfo(hwnd, SB_VERT, &scrollinfo, TRUE);

    m->Result = 0;
  }
  return;
case WM_MOUSEMOVE:
  {
    if (_panning)
    {
      POINT pt;
      ::GetCursorPos(&pt);
      long dx = _ms_cur_x - pt.x;
      long dy = _ms_cur_y - pt.y;

      if (dx || dy)
      {
        mp_imp->OnScroll(dx, dy);
        SetScrolls();
        _ms_cur_x = pt.x;
        _ms_cur_y = pt.y;
      }
    }
  }
  break;
case WM_LBUTTONDOWN:
  {
    POINT pt;
    ::GetCursorPos(&pt);
    _ms_cur_x = pt.x;
    _ms_cur_y = pt.y;
    SetCapture(hwnd);
    _panning = true;

    //SetCursor(_drag_cur);
  }
  break;
case WM_LBUTTONUP:
  {
    if (_panning) {
      ::ReleaseCapture();
      _panning = false;
    }
  }
  break;

} // end of case