Hide

SftPrintPreview/DLL 2.0 - Print Preview Control for C/C++

Display
Print

PreviewPages Sample (C)

This sample illustrates application-generated output.

The source code is located at C:\Program Files (x86)\Softelvdm\SftPrintPreview DLL 2.0\Samples\C\PreviewPages\PreviewPages.c or C:\Program Files\Softelvdm\SftPrintPreview DLL 2.0\Samples\C\PreviewPages\PreviewPages.c (on 32-bit Windows versions).


#include <windows.h>
#include <stdlib.h>

#include <crtdbg.h>

#include "SftPrintPreview.h"                     /* SftPrintPreview/DLL Header File */

#include "resource.h"

#define IDC_PREVIEW         100         // ID for preview control

#define LINETEXT TEXT("Softel vdm, Inc. - www.softelvdm.com")

/**********************************************************************/
/*                              Globals                               */
/**********************************************************************/

#define MAINWINDOWCLASS "SampleMainFrame"

HINSTANCE m_hInstance;                  // App Instance Handle
HWND m_hwndPreview;                     // Preview window
HFONT m_hPrintFont;                     // printer font

/**********************************************************************/
/*                            Page Printing                           */
/**********************************************************************/

static void PrintOnePage(LPSFTPRINTPREVIEW_DRAWINFO lpInfo)
{
    // Print one page (can occur multiple times)
    // lpInfo->absPage has the absolute page # to print (0..n)
    // lpInfo->previousVisitedPageInfo contains the value you returned in
    // lpInfo->visitedPageInfo when you finished printing the previous page
    // This allows you to simply restart where you left off.
    // The information you return in lpInfo->visitedPageInfo is of type
    // SFTPRINTPREVIEW_DWORD_PTR, so it can be a simple counter or
    // even a pointer to stored, cached information.

    // In this example we print 1 bitmap, then 50 lines of text,
    // 20 times

    // We use lpInfo->previousVisitedPageInfo to resume printing.
    // We simply start at 0 and add 1 for each bitmap or line we
    // printed. Using a simple formula, we can determine where we
    // left off.  In an application, the concept remains the same, but
    // instead of a simple counter, you could use lpInfo->visitedPageInfo
    // to store a pointer to cached information.

    int counter = (int) lpInfo->previousVisitedPageInfo;// we left off here on the previos page

    int xPrinter, yPrinter;
    HBITMAP hBitmap = NULL;

    // starting output position on this page
    xPrinter = lpInfo->OutputRectDisplayPix.left;
    yPrinter = lpInfo->OutputRectDisplayPix.top;

    // load bitmap
    hBitmap = LoadBitmap(m_hInstance, MAKEINTRESOURCE(IDB_WEBPAGE));
    _ASSERT(hBitmap);

    for ( ; ; ) {
        int wPrinter, hPrinter, w, h;

        if (counter >= (1+50)*20) {
            // we have printed 1 bitmap and 50 lines 20 times, we're done
            lpInfo->lastPage = lpInfo->absPage; // return that this is the last page
            break;
        }

        if ((counter % (50+1)) == 0) {
            // Print a bitmap

            // get bitmap size
            SftPrintPreview_GetBitmapSize(hBitmap, lpInfo->hDCPrinter, &wPrinter, &hPrinter, &w, &h);
            // make sure entire image fits on remaining page
            if (yPrinter != lpInfo->OutputRectDisplayPix.top && yPrinter + hPrinter > lpInfo->OutputRectDisplayPix.bottom)
                break;
            // print bitmap, horizontally centered
            // this code does not handle if the bitmap is too large for the remaining space
            SftPrintPreview_PrintBitmap(hBitmap, lpInfo->hDC, xPrinter +(lpInfo->OutputRectDisplayPix.right-lpInfo->OutputRectDisplayPix.left-wPrinter)/2, 
                   yPrinter, wPrinter, hPrinter, w, h);

            yPrinter += hPrinter; // next available space
        } else {
            // Print line
            RECT rect, OutRect;
            HFONT hOldFont = SelectObject(lpInfo->hDC, m_hPrintFont);
            SetTextColor(lpInfo->hDC, RGB(0,0,0));

            // get text size
            SetRectEmpty(&rect);
            DrawText(lpInfo->hDC, LINETEXT, -1, &rect, DT_LEFT| DT_TOP | DT_SINGLELINE | DT_CALCRECT);
            // make sure text fits on remaining page
            if (yPrinter + (rect.bottom-rect.top) > lpInfo->OutputRectDisplayPix.bottom)
                break;

            OutRect = lpInfo->OutputRectDisplayPix;
            OutRect.top = yPrinter;
            DrawText(lpInfo->hDC, LINETEXT, -1, &OutRect, DT_CENTER| DT_TOP | DT_SINGLELINE);

            yPrinter += rect.bottom-rect.top; // next available space

            hOldFont = SelectObject(lpInfo->hDC, hOldFont);

        }
        ++counter;  // one more item done
    }

    if (hBitmap)
        DeleteObject(hBitmap);

    lpInfo->visitedPageInfo = counter; // we left off here
}


BOOL CALLBACK RenderPages_Callback(LPSFTPRINTPREVIEW_DRAWINFO lpInfo)
{
    switch (lpInfo->function) {
    case SFTPRINTPREVIEW_PRINT_INIT: {
        // printing/preview is about to begin
        // initialize any "expensive" resources you may need
        int height = MulDiv(10, GetDeviceCaps(lpInfo->hDCPrinter, LOGPIXELSY), 72);// 10 point font
        m_hPrintFont = CreateFont(- height, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET,
            OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FF_DONTCARE|DEFAULT_PITCH,
            TEXT("Arial"));
        _ASSERT(m_hPrintFont);
        return TRUE;
     }
    case SFTPRINTPREVIEW_PRINT_TERM:
        // printing/preview is ending
        // free resources no longer needed
        if (m_hPrintFont)
            DeleteObject(m_hPrintFont);
        m_hPrintFont = NULL;
        return TRUE;
    case SFTPRINTPREVIEW_PRINT_ONEPAGE:
        // print one page (can occur multiple times)
        PrintOnePage(lpInfo);
        return TRUE;
    case SFTPRINTPREVIEW_PRINT_CLEARCACHE:
        // the output needs to be reformatted - clear any cached information
        return TRUE;
    case SFTPRINTPREVIEW_PRINT_DIMENSIONS:
        // determine best output width for current data
        // iContentSizing and contentWidth have suggested width and display style
        // If you want to manage the entire printable area (inside the margins),
        // no action is required
        return TRUE;
    default:
        return FALSE;
    }
}

/**********************************************************************/
/*                      Initialize Preview Window                     */
/**********************************************************************/

void InitPreviewWindow(HWND hwndCtl)
{
    // retrieve current control settings
    SFTPRINTPREVIEW_CONTROL Ctl;
    Ctl.cbSize = sizeof(SFTPRINTPREVIEW_CONTROL);
    if (!SftPrintPreview_GetControlInfo(hwndCtl, &Ctl)) {
        _ASSERT(0); // the SFTPRINTPREVIEW_CONTROL structure's cbSize member wasn't initialized properly
        return;
    }

    // set all desired options
    Ctl.numPageRows = 1;                // default to 1x2 pages
    Ctl.numPageGroups = 2;
    Ctl.zoom = 0;                       // start out with multiple pages
    lstrcpy(Ctl.szOutputName, TEXT("SftPrintPreview PreviewPages Sample Output")); // job name when printing
    lstrcpy(Ctl.szHeaderRight, TEXT("SftPrintPreview/DLL PreviewPages Sample"));
    lstrcpy(Ctl.szFooterLeft, TEXT("www.softelvdm.com"));

    Ctl.fCenterOnClick = FALSE;
    Ctl.fDragPage  = TRUE;
    Ctl.iZoomStyle = SFTPRINTPREVIEW_ZOOMSTYLE_BOTHBUTTONS_EXACT;

    if (!SftPrintPreview_SetControlInfo(hwndCtl, &Ctl)) {
        int errorValue = Ctl.errorValue;
        _ASSERT(0); // an error occurred, check errorValue for error code
        return;
    }
}

void DefineContents(HWND hwndCtl)
{
    SFTPRINTPREVIEW_CONTROL Ctl;

    Ctl.cbSize = sizeof(SFTPRINTPREVIEW_CONTROL);
    if (!SftPrintPreview_GetControlInfo(hwndCtl, &Ctl)) {
        _ASSERT(0); // the SFTPRINTPREVIEW_CONTROL structure's cbSize member wasn't initialized properly
        return;
    }

    // define desired contents to preview/print
    Ctl.lpDrawPageWorkArea = (SFTPRINTPREVIEW_DWORD_PTR) NULL;// no workarea needed
    Ctl.lpDrawInfoProc = RenderPages_Callback;// callback for our pages
    Ctl.hwndContent = NULL;             // no window
    Ctl.hwndData = NULL;                // no data window (content window is data window)
    Ctl.iContentSizing = SFTPRINTPREVIEW_CONTENTSIZING_SHRINKTOFIT;// shrink to fit on page

    if (!SftPrintPreview_SetControlInfo(hwndCtl, &Ctl)) {
        int errorValue = Ctl.errorValue;
        _ASSERT(0); // an error occurred, check errorValue for error codes
        return;
    }
}

/**********************************************************************/
/*                          Main Window Proc                          */
/**********************************************************************/

LRESULT CALLBACK MainWindowProc(HWND hwndMain, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg) {
    case WM_CREATE:
        // create a preview window
        m_hwndPreview = CreateWindow(TEXT(SFTPRINTPREVIEW_CLASS), NULL,
                WS_CHILD|WS_VISIBLE, 0, 0, 0, 0, hwndMain, (HMENU) IDC_PREVIEW, m_hInstance, NULL);
        _ASSERT(m_hwndPreview);
        if (!m_hwndPreview) return -1;

        InitPreviewWindow(m_hwndPreview);
        DefineContents(m_hwndPreview);
        SetFocus(m_hwndPreview);
        ShowWindow(hwndMain, SW_SHOW);

        break;

    case WM_DESTROY:
        if (m_hwndPreview)
            DestroyWindow(m_hwndPreview);
        m_hwndPreview = NULL;
        break;

    case WM_SIZE: {
        RECT rect;
        GetClientRect(hwndMain, &rect);
        MoveWindow(m_hwndPreview, 0, 0, rect.right-rect.left, rect.bottom-rect.top, TRUE);
        break;
     }

    case WM_SETFOCUS: 
        SetFocus(m_hwndPreview);
        break;

    case WM_COMMAND: {
        HWND hwndCtl = (HWND) lParam;
        int id = LOWORD(wParam);
        int code = HIWORD(wParam);
        if (hwndCtl) {
            switch (id) {
            case IDC_PREVIEW:
                switch (code) {
                case SFTPRINTPREVIEWN_STARTPRINTING:
                    SftPrintPreview_Print(hwndCtl, hwndMain);
                    break;
                }
                break;
            }
        }
        break;
     }
    case WM_NOTIFY: {
        int id = (int) wParam; 
        LPNMHDR pnmh = (LPNMHDR) lParam;
        switch (id) {
        case IDC_PREVIEW:
            switch (pnmh->code) {
            case NM_SFTPRINTPREVIEW_CLOSE_CODE: { // user wants to close
                NM_SFTPRINTPREVIEW_CLOSE* pNtfy = (NM_SFTPRINTPREVIEW_CLOSE*) lParam;
                SendMessage(hwndMain, WM_CLOSE, 0, 0);
                break;
             }
            case NM_SFTPRINTPREVIEW_HELP_CODE: { // help requested
                NM_SFTPRINTPREVIEW_HELP* pNtfy = (NM_SFTPRINTPREVIEW_HELP*) lParam;
                MessageBox(hwndMain, TEXT("Sorry, this sample application doesn't include online help."), TEXT("SftPrintPreview/DLL"), MB_OK);
                break;
             }
            case NM_SFTPRINTPREVIEW_PAGESETUP_CODE: { // Page setup requested
                SftPrintPreview_PageSetup(m_hwndPreview, hwndMain);
                break;
             }
            }
            break;
        }
        break;
     }

    case WM_CLOSE:
        PostQuitMessage(1);
        break;
    }
    return DefWindowProc(hwndMain, uMsg, wParam, lParam);
}

/**********************************************************************/
/*                              WinMain                               */
/**********************************************************************/

int PASCAL WinMain(HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR lpszCmdLine, int cmdShow)
{
    WNDCLASS wndClass;
    HWND hwndMain;
    MSG msg;

    m_hInstance = hinst;

    msg.wParam = 0;

    // Register with SftPrintPreview/DLL
    SftPrintPreview_RegisterApp(m_hInstance);

    // Register main frame window
    memset(&wndClass, 0, sizeof(wndClass));
    wndClass.lpfnWndProc = MainWindowProc;
    wndClass.hInstance = m_hInstance;
    wndClass.hIcon = LoadIcon(m_hInstance, MAKEINTRESOURCE(IDI_ICON1));
    wndClass.hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
    wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    wndClass.lpszClassName = TEXT(MAINWINDOWCLASS);
    if (!RegisterClass(&wndClass)) {
        _ASSERT(0);
        return -1;
    }

    // Create main frame window
    hwndMain = CreateWindowEx(0, TEXT(MAINWINDOWCLASS), TEXT("SftPrintPreview/DLL PreviewPages Sample"), 
            WS_OVERLAPPEDWINDOW|WS_SIZEBOX|WS_VISIBLE,
            CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 
            NULL, NULL, //no menu for this sample
            m_hInstance, NULL);
    _ASSERT(hwndMain);
    if (hwndMain) {

        MessageBox(hwndMain, TEXT("This example demonstrates application-generated output.\r\n\r\nIt prints one bitmap and 50 lines of text a total of 20 times.  ")
            TEXT("The included source code illustrates how an application can print one page at a time, with an easy ")
            TEXT("mechanism to keep track of restart positions."), TEXT("SftPrintPreview/DLL"), MB_OK | MB_ICONINFORMATION);

        for ( ; ; ) {
            if (GetMessage(&msg, NULL, 0, 0) == 0)
                break;
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    if (!UnregisterClass(TEXT(MAINWINDOWCLASS), m_hInstance))
        _ASSERT(0);

    SftPrintPreview_UnregisterApp(m_hInstance); /* Unregister from SftPrintPreview/DLL */

    return (int) msg.wParam;
}

Last Updated 08/13/2020 - (email)
© 2024 Softel vdm, Inc.