//--------------------------------------------------------------------------------------- // Copyright (c) 2001-2012 by PDFTron Systems Inc. All Rights Reserved. // Consult legal.txt regarding legal and license information. //--------------------------------------------------------------------------------------- // This sample shows how to add PDF viewer control in a basic Win32 project. // The sample uses a number of built-in features from PDFViewCtrl to implement // document navigation, text highlighting, markup, and editing. // // PDFViewCtrl offers built-in support for a number of PDF tools (including markup, // link creation, forms, text selection, etc) and user interface elements (such as // navigation panel, find text, etc). PDFViewCtrl is highly configurable allowing // users to implement custom tools or to modify behavior of built-in tools. // Default user interface elements such as the navigation panel can be replaced // with a custom implementation and users can override window events and various // document actions. For example, by default, PDFViewCtrl will launch URL links // in a web browser and will jump to a destination for 'GoTo' actions. The default // behavior can be overridden using a custom callback function (as shown in the // following sample). // // Besides PDFViewCtrl, the C++ version of PDFNet SDK also includes a low-level class // called PDFView. Because PDFView does not process any window messages and does not // implement built-in tools it is only suitable for very low-level control development // (e.g. if you would like to implement a control similar to PDFViewCtrl from scratch). // The basic use of PDFView is illustrated in PDFView sample project. //--------------------------------------------------------------------------------------- #include "stdafx.h" #include "resource.h" #include #include #include #include #include #include #include #include #include #include #include using namespace pdftron; using namespace PDF; #define MAX_LOADSTRING 100 // Global Variables: HINSTANCE hInst; // current instance TCHAR szTitle[MAX_LOADSTRING]; // The title bar text TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name UString m_doc_name; std::auto_ptr mp_doc; std::auto_ptr m_view; // Forward declarations of functions included in this code module: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); // TODO: Place code here. MSG msg; HACCEL hAccelTable; // Initialize global strings LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadString(hInstance, IDC_PDFVIEWSIMPLE, szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance); // Perform application initialization: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_PDFVIEWSIMPLE)); // Main message loop: while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int) msg.wParam; } // // FUNCTION: MyRegisterClass() // // PURPOSE: Registers the window class. // // COMMENTS: // // This function and its usage are only necessary if you want this code // to be compatible with Win32 systems prior to the 'RegisterClassEx' // function that was added to Windows 95. It is important to call this function // so that the application will get 'well formed' small icons associated // with it. // ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_PDFVIEWSIMPLE)); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = MAKEINTRESOURCE(IDC_PDFVIEWSIMPLE); wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); return RegisterClassEx(&wcex); } typedef std::pair< int, PDF::PDFViewCtrl::ToolMode > ToolModeMapType; const ToolModeMapType toolModeMap[] = { ToolModeMapType( IDM_TOOL_PAN , PDF::PDFViewCtrl::e_pan ), ToolModeMapType( IDM_TOOL_STRUCTURALSELECTION , PDF::PDFViewCtrl::e_text_struct_select ), ToolModeMapType( IDM_TOOL_RECTANGLESELECTION , PDF::PDFViewCtrl::e_text_rect_select ), ToolModeMapType( IDM_TOOL_RECTANGLEZOOMIN , PDF::PDFViewCtrl::e_zoom_in ), ToolModeMapType( IDM_TOOL_RECTANGLEZOOMOUT , PDF::PDFViewCtrl::e_zoom_out ), ToolModeMapType( IDM_TOOL_ANNOTATIONEDITING , PDF::PDFViewCtrl::e_annot_edit ), ToolModeMapType( IDM_TOOL_TEXTANNOTCREATION , PDF::PDFViewCtrl::e_text_annot_create ), ToolModeMapType( IDM_TOOL_LINECREATION , PDF::PDFViewCtrl::e_line_create ), ToolModeMapType( IDM_TOOL_ARROWCREATION , PDF::PDFViewCtrl::e_arrow_create ), ToolModeMapType( IDM_TOOL_RECTANGLECREATION , PDF::PDFViewCtrl::e_rect_create ), ToolModeMapType( IDM_TOOL_OVALCREATION , PDF::PDFViewCtrl::e_oval_create ), ToolModeMapType( IDM_TOOL_FREEHANDTOOL , PDF::PDFViewCtrl::e_ink_create ), ToolModeMapType( IDM_TOOL_STAMPCREATIONTOOL , PDF::PDFViewCtrl::e_stamp_create ), ToolModeMapType( ID_TOOL_HIGHLIGHTTOOL , PDF::PDFViewCtrl::e_highlight_create ), ToolModeMapType( ID_TOOL_UNDERLINETOOL , PDF::PDFViewCtrl::e_underline_create ), ToolModeMapType( ID_TOOL_STRIKEOUTTOOL , PDF::PDFViewCtrl::e_strikeout_create ), ToolModeMapType( ID_TOOL_SQUIGGLYUNDERLINETOOL , PDF::PDFViewCtrl::e_squiggly_create ), ToolModeMapType( ID_TOOL_CALLOUTTEXTBOXTOOL , PDF::PDFViewCtrl::e_calloutbox_create ), ToolModeMapType( ID_TOOL_SIMPLETEXTBOXTOOL , PDF::PDFViewCtrl::e_text_box_create ), ToolModeMapType( ID_TOOL_POLYGONTOOL , PDF::PDFViewCtrl::e_polygon_create ), ToolModeMapType( ID_TOOL_POLYLINETOOL , PDF::PDFViewCtrl::e_polyline_create ), ToolModeMapType( ID_TOOL_FILEATTACHMENTTOOL , PDF::PDFViewCtrl::e_file_attachment ), ToolModeMapType( ID_TOOL_SOUNDATTACHMENTTOOL , PDF::PDFViewCtrl::e_sound_attachment ), ToolModeMapType( ID_TOOL_MOVIEINSERTIONTOOL , PDF::PDFViewCtrl::e_movie_attachment ), ToolModeMapType( ID_TOOL_CARETPLACEMENTTOOL , PDF::PDFViewCtrl::e_caret_create ), ToolModeMapType( ID_TOOL_REDACTIONTOOL , PDF::PDFViewCtrl::e_redaction_create ), ToolModeMapType( ID_TOOL_TEXTFIELDCREATION , PDF::PDFViewCtrl::e_text_field_create ), ToolModeMapType( ID_TOOL_CHECKBOXCREATIONTOOL , PDF::PDFViewCtrl::e_check_box_create ), ToolModeMapType( ID_TOOL_RADIOBUTTON , PDF::PDFViewCtrl::e_radio_button_create ), ToolModeMapType( ID_TOOL_LISTBOX , PDF::PDFViewCtrl::e_list_box_create ), ToolModeMapType( ID_TOOL_COMBOBOX , PDF::PDFViewCtrl::e_combo_box_create ), ToolModeMapType( ID_TOOL_BUTTONCREATIONTOOL , PDF::PDFViewCtrl::e_button_create ) }; const ToolModeMapType* const toolModeMapEnd = toolModeMap + sizeof(toolModeMap)/sizeof(ToolModeMapType); struct ToolModePred { int m_code; ToolModePred( int c ) : m_code(c) {} bool operator()( ToolModeMapType tp ) { return tp.first == m_code; } }; // FUNCTION: InitInstance(HINSTANCE, int) // // PURPOSE: Saves instance handle and creates main window // // COMMENTS: // // In this function, we save the instance handle in a global variable and // create and display the main program window. // BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { PDFNet::Initialize(); // PDFNet::SetColorManagement(); HWND hWnd; hInst = hInstance; // Store instance handle in our global variable hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if (!hWnd) { return FALSE; } ShowWindow(hWnd, nCmdShow); // Optional: PDFViewCtrl can save its UI state across different sessions. // In this case the config file is save in the current working folder. //m_view->LoadCurrentConfiguration( "my.cfg" ); UpdateWindow(hWnd); return TRUE; } void ErrorCallback(const char* message, void* custom_data) { static bool reported_once = false; if (!reported_once) { reported_once = true; HWND hwnd = (HWND) custom_data; // Case custom data to the expected argument. ::MessageBox(hwnd, message, "Error", MB_OK); } } TRN_Bool MyActionHandler( TRN_Action act, void* custom_data ) { Action action(act); if (!action.IsValid()) return 1; HWND hwnd = (HWND) custom_data; // Case custom data to the expected argument. Action::Type type = action.GetType(); if (type == Action::e_GoTo) { Destination dest = action.GetDest(); if (!dest.IsValid()) { MessageBox(hwnd, "Destination is not valid", "MyURLActionHandler", MB_OK | MB_ICONEXCLAMATION); } else { int page_num = dest.GetPage().GetIndex(); char buf[256]; sprintf(buf, " Links to: page number %d in this document", page_num); MessageBox(hwnd, buf, "MyURLActionHandler", MB_OK | MB_ICONEXCLAMATION); return 0; // -> execute the default action handler. } } else if (type == Action::e_URI) { UString uri; action.GetSDFObj().Get("URI").Value().GetAsPDFText(uri); char buf[256]; sprintf(buf, " Links to: %s", uri.ConvertToAscii().c_str()); MessageBox(hwnd, buf, "MyURLActionHandler", MB_OK); } else { MessageBox(hwnd, "Other Action Type -> Handled by PDFViewCtrl", "MyURLActionHandler", MB_OK); return 0; // -> execute the default action handler. } // If this function returns true, PDFViewCtrl will not execute the default // action internally (in case of URL the default action is to open the URL // link in a web browser). return 1; } TRN_Bool MyMouseDoubleClickEvent( PDFViewCtrl::MouseEvent* evt, void* custom_data) { if (!evt->m_pdfviewctrl_processed) // Display the message box before the message is processed by PDFNet? { HWND hwnd = (HWND) custom_data; // Case custom data to the expected argument. MessageBox(hwnd, "Example of a custom event", "MyMouseDoubleClickEvent", MB_OK); return false; // execute built-in event. To skip event processing in PDFViewCtrl return true. } return false; } LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; static HMENU hMenu ; switch (message) { case WM_CREATE: { m_view = std::auto_ptr(new pdftron::PDF::PDFViewCtrl(hWnd, hInst)); hMenu = LoadMenu (hInst, MAKEINTRESOURCE(IDC_PDFVIEWSIMPLE)); hMenu = GetSubMenu (hMenu, 0); // m_view->SetProgressiveRendering(false); // m_view->SetPageBorderVisibility(false); // m_view->SetPageSpacing(0, 0, 0, 0); // m_view->SetDefaultPageColor(255, 255, 255); // m_view->ShowNavPanel(true); // m_view->ShowNavToolbar(true); // m_view->SetAntiAliasing( true ); // m_view->SetGamma(0.01); m_view->SetErrorReportHandler(ErrorCallback, hWnd); m_view->SetActionHandler(MyActionHandler, hWnd); PDFViewCtrl::EventHandlers my_handlers; my_handlers.mouse_left_dclick = MyMouseDoubleClickEvent; my_handlers.custom_data = hWnd; m_view->SetCustomEventHandlers( &my_handlers ); } break; case WM_COMMAND: { wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); const ToolModeMapType* const wmId_it = std::find_if( toolModeMap, toolModeMapEnd, ToolModePred(wmId) ); if( wmId_it != toolModeMapEnd ) m_view->SetToolMode( wmId_it->second ); else { switch (wmId) { case IDM_ABOUT: // DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; case IDM_FILE_PRINT: { if(m_view->GetDoc()) m_view->Print(); } break; case IDM_FILE_SAVEAS: { if(m_view->GetDoc()) { TCHAR szFile[256] = { 0 }; TCHAR *szFilter =TEXT("PDF Files (*.pdf)\0") TEXT("*.pdf\0") TEXT("All Files\0") TEXT("*.*\0"); OPENFILENAME ofn; ZeroMemory(&ofn, sizeof(OPENFILENAME)); ofn.lStructSize=sizeof(OPENFILENAME); ofn.lpstrFilter=szFilter; ofn.nFilterIndex=1; ofn.lpstrFile=szFile; ofn.nMaxFile=sizeof(szFile); ofn.lpstrTitle=_T("Save PDF File"); ofn.nMaxFileTitle=sizeof(ofn.lpstrFile); //===Start the File Dialog if(GetSaveFileName(&ofn)) { m_view->GetDoc()->Save(UString((const char*)ofn.lpstrFile), SDF::SDFDoc::e_linearized, 0); } } } break; case IDM_FILE_SAVE: { if(m_view->GetDoc()) { if(m_view->GetDoc()) { m_view->GetDoc()->Save(m_doc_name, SDF::SDFDoc::e_remove_unused, 0); } } } break; case IDM_FILE_OPEN: { //===File path TCHAR szFile[256] = { 0 }; //===Filter TCHAR *szFilter =TEXT("PDF Files (*.pdf)\0") TEXT("*.pdf\0") TEXT("All Files\0") TEXT("*.*\0"); OPENFILENAME ofn; ZeroMemory(&ofn, sizeof(OPENFILENAME)); ofn.lStructSize=sizeof(OPENFILENAME); ofn.lpstrFilter=szFilter; ofn.nFilterIndex=1; ofn.lpstrFile=szFile; ofn.nMaxFile=sizeof(szFile); ofn.lpstrTitle=_T("Open PDF File"); ofn.nMaxFileTitle=sizeof(ofn.lpstrFile); //===Start the File Dialog if(GetOpenFileName(&ofn)) { m_doc_name=UString((const char*)ofn.lpstrFile); try{ std::auto_ptr doc(new PDF::PDFDoc(m_doc_name)); if(m_view->SetDoc(*doc)) { mp_doc=doc; // m_view->ShowNavPanel(true); // m_view->ShowNavToolbar(true); } } catch(...) { ::MessageBox(hWnd,"An error occurred while opening a file","PDFViewSimple Error",MB_OK); } } } break; case IDM_PAGELAYOUT_SINGLEPAGE: { m_view->SetPagePresentationMode(PDF::PDFViewCtrl::e_single_page); } break; case IDM_PAGELAYOUT_SINGLECONTINUOUS: { if(m_view->GetDoc()) { m_view->SetPagePresentationMode(PDF::PDFViewCtrl::e_single_continuous); } } break; case IDM_PAGELAYOUT_FACING: { m_view->SetPagePresentationMode(PDF::PDFViewCtrl::e_facing); } break; case IDM_PAGELAYOUT_FACINGCONTINUOUS: { if(m_view->GetDoc()) { m_view->SetPagePresentationMode(PDF::PDFViewCtrl::e_facing_continuous); } } break; case IDM_PAGELAYOUT_FACING_COVER: { if(m_view->GetDoc()) { m_view->SetPagePresentationMode(PDF::PDFViewCtrl::e_facing_cover); } } break; case IDM_PAGELAYOUT_FACINGCONTINUOUS_COVER: { if(m_view->GetDoc()) { m_view->SetPagePresentationMode(PDF::PDFViewCtrl::e_facing_continuous_cover); } } break; case IDM_PAGEVIEWMODE_FITPAGE: { m_view->SetPageViewMode(PDF::PDFViewCtrl::e_fit_page); } break; case IDM_PAGEVIEWMODE_FITWIDTH: { m_view->SetPageViewMode(PDF::PDFViewCtrl::e_fit_width); } break; case IDM_VIEW_ZOOMIN: { if(m_view->GetDoc()) { m_view->SetZoom(m_view->GetZoom()*2); } } break; case IDM_VIEW_ZOOMOUT: { if(m_view->GetDoc()) { m_view->SetZoom(m_view->GetZoom()/2); } } break; case IDM_PAGENAVIGATION_GOTONEXTPAGE: { if(m_view->GetDoc()) { m_view->GotoNextPage(); } } break; case IDM_PAGENAVIGATION_GOTOPREVIOUSPAGE: { if(m_view->GetDoc()) { m_view->GotoPreviousPage(); } } break; case IDM_PAGENAVIGATION_GOT: { if(m_view->GetDoc()) { m_view->GotoLastPage(); } } break; case IDM_PAGENAVIGATION_GOTOFIRSTPAGE: { if(m_view->GetDoc()) { m_view->GotoFirstPage(); } } break; case IDM_EDIT_COPY: { if(m_view->GetDoc()) { m_view->Copy(); } } break; case IDM_EDIT_FIND: { if(m_view->GetDoc()) { m_view->Find(); } } break; case IDM_EDIT_SELECTALL: { if(m_view->GetDoc()) { m_view->SelectAll(); } } break; case ID_TOGGLE_NAV_PANEL: m_view->ShowNavPanel(!m_view->IsNavPanelVisible()); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } } } break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // TODO: Add any drawing code here... EndPaint(hWnd, &ps); break; case WM_CLOSE: //m_view->SaveCurrentConfiguration("my.cfg"); m_view.reset(); DestroyWindow(hWnd); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; case WM_SIZE: // this is never getting called, wxWidgets handles these events internally break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } // Message handler for about box. INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { UNREFERENCED_PARAMETER(lParam); switch (message) { case WM_INITDIALOG: return (INT_PTR)TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, LOWORD(wParam)); return (INT_PTR)TRUE; } break; } return (INT_PTR)FALSE; }