Low-Level DigitalPaint: Initializing and Freeing a Paint Handle

Take the following steps to create a new paint handle:

Start a new project as follows:

1.

 Run Microsoft Visual Studio 2005, select File à New à Project, and do the following:

 

Expand Visual C++ tree, if it is not already expanded.

 

Select Win32 from the sub tree.

 

Select Win32 Project from the right window.

 

In the Project name text box, specify Tutorial.

 

In the Location text box, specify the path of the project.

 

Click the OK button.

2.

In the overview window, click Next.

3.

In the Application Type step dialog box, do the following:

 

Select Windows application.

 

Be sure to un-check the Empty project checkbox.

 

Click the Finish button.

4.

Add the following Menu to the tutorial.rc:

 

In File menu:

 

 

&Open…

with ID = IDM_FILE_OPEN

5.

In Tutorial.cpp replace the WndProc procedure with the following code:

static LRESULT WINAPI WndProc ( HWND hWnd, L_UINT uMessage, WPARAM wParam, LPARAM lParam )

{

   static BITMAPHANDLE hBitmap ;

   static RECT rcView ;

   static L_INT nVScroll = 0 ;

   static L_INT nHScroll = 0 ;

   static L_INT nZoomFactor = 100 ;

   static pPAINTHANDLE pPaint ;

  

   switch( uMessage )

   {

   case WM_CREATE:

      if ( SUCCESS == L_PntInit ( &pPaint ) )

      {

         return 0L ;

      }

      else

      {

         return -1L ;

      }

 

     

   case WM_DESTROY:

      if ( hBitmap.Flags.Allocated )

      {

         L_FreeBitmap( &hBitmap ) ;

      }

     

      if ( SUCCESS == L_PntIsValid ( pPaint ) )

      {

         L_PntFree ( pPaint ) ;

      }

 

      PostQuitMessage ( 0 ) ;

     

      return 0L ;

     

   case WM_SIZE:

      OnSize ( hWnd,

               &hBitmap,

               &rcView,

               LOWORD ( lParam ),

               HIWORD ( lParam ),

               nZoomFactor,

               &nHScroll,

               &nVScroll ) ;

      break ;

     

   case WM_HSCROLL:

      OnHScroll ( hWnd,

                  LOWORD ( wParam ),

                  nZoomFactor,

                  &rcView,

                  &nHScroll,

                  &nVScroll ) ;

      break ;

     

   case WM_VSCROLL:

      OnVScroll ( hWnd,

                  LOWORD ( wParam ),

                  nZoomFactor,

                  &rcView,

                  &nHScroll,

                  &nVScroll ) ;

     

      break ;

     

   case WM_PAINT:

      OnPaint ( hWnd, &hBitmap, &rcView) ;

      break ;

     

   case WM_COMMAND:

      switch( LOWORD( wParam ) )

      {

      case IDM_FILE_OPEN:

         {

            BITMAPHANDLE hTempBitmap ;

            HDC hDC ;

           

           

            if ( OnOpen ( hWnd, &hTempBitmap ) )

            {

               if ( hBitmap.Flags.Allocated )

               {

                  L_FreeBitmap( &hBitmap ) ;

               }

              

               L_CopyBitmapHandle( &hBitmap, &hTempBitmap, sizeof(BITMAPHANDLE)) ;

              

               hDC = GetDC ( hWnd ) ;

              

 

               ReleaseDC ( hWnd, hDC ) ;

              

               {//ADJUST WINDOW SIZE

                 

                  RECT  rcWindow ;

                  L_INT nWidth, nHeight ;

                 

                 

                  SystemParametersInfo ( SPI_GETWORKAREA, 0, &rcWindow, 0 ) ;

                 

                  nWidth = min ( MulDiv ( BITMAPWIDTH ( &hBitmap ), nZoomFactor, 100 ),

                                 ( rcWindow.right  - rcWindow.left ) ) ;

                 

                  nHeight = min ( MulDiv ( BITMAPHEIGHT ( &hBitmap ), nZoomFactor, 100 ),

                                  ( rcWindow.bottom - rcWindow.top  ) ) ;

                 

                  MoveWindow ( hWnd,

                               0,

                               0,

                               nWidth,

                               nHeight,

                               TRUE ) ;

                 

               }//ADJUST WINDOW SIZE

              

               InvalidateRect ( hWnd, NULL, TRUE ) ;

            }

         }

        

         return 0L ;

        

      case IDM_EXIT:

         PostMessage ( hWnd, WM_CLOSE, 0, 0 ) ;

         return 0L ;

      }

     

      break ;

   }

  

   return DefWindowProc ( hWnd, uMessage, wParam, lParam ) ;

}

6.

Add the following code right before WndProc procedure:

 

static L_VOID OnSize

(

   HWND hWnd,

   pBITMAPHANDLE pBitmap,

   LPRECT prcView,

   L_INT cx,

   L_INT cy,

   L_INT nZoom,

   L_INT *pnHScroll,

   L_INT *pnVScroll

)

{

   SCROLLINFO si ;

   L_INT      nXOffset, nYOffset ;

 

 

   if ( NULL != pBitmap && pBitmap->Flags.Allocated )

   {

      si.cbSize = sizeof ( SCROLLINFO ) ;

      si.fMask  = SIF_ALL ;

     

      // vertical scroll.

      GetScrollInfo ( hWnd, SB_VERT, &si ) ;

      si.nMin  = 0 ;

      si.nMax  = BITMAPHEIGHT ( pBitmap ) ;

      si.nPage = MulDiv ( cy, 100, nZoom ) ;

     

      SetScrollInfo ( hWnd, SB_VERT, &si, TRUE ) ;

     

      GetScrollInfo ( hWnd, SB_VERT, &si ) ;

     

      *pnVScroll = si.nPos ;

     

      // horizontal scroll

      GetScrollInfo ( hWnd, SB_HORZ, &si ) ;

      si.nMin  = 0 ;

      si.nMax  = BITMAPWIDTH ( pBitmap ) ;

      si.nPage = MulDiv ( cx, 100, nZoom ) ;

     

      SetScrollInfo ( hWnd, SB_HORZ, &si, TRUE ) ;

      

      GetScrollInfo ( hWnd, SB_HORZ, &si ) ;

     

      *pnHScroll = si.nPos ;

   }

   else

   {

      si.cbSize = sizeof ( SCROLLINFO ) ;

      si.fMask  = SIF_RANGE ;

      si.nMin   = 0 ;  

      si.nMax   = 0 ;

     

      SetScrollInfo ( hWnd, SB_VERT, &si, TRUE ) ;

      SetScrollInfo ( hWnd, SB_HORZ, &si, TRUE ) ;

     

      *pnHScroll = 0 ;

      *pnVScroll = 0 ;

   }

  

   // set the painting rectangel.

   SetRect ( prcView, 0, 0, BITMAPWIDTH ( pBitmap ), BITMAPHEIGHT ( pBitmap ) ) ;

  

   if ( nZoom < 100 )

   {

      nXOffset = MulDiv ( *pnHScroll, 100, nZoom ) ; 

      nYOffset = MulDiv ( *pnVScroll, 100, nZoom ) ;

   }

   else

   {

      nXOffset = *pnHScroll ; 

      nYOffset = *pnVScroll ;

   }

  

   OffsetRect ( prcView, - nXOffset, - nYOffset ) ;

  

   prcView->left   = MulDiv ( prcView->left,   nZoom, 100 ) ;

   prcView->top    = MulDiv ( prcView->top,    nZoom, 100 ) ;

   prcView->right  = MulDiv ( prcView->right,  nZoom, 100 ) ;

   prcView->bottom = MulDiv ( prcView->bottom, nZoom, 100 ) ;

}

 

L_VOID OnHScroll

(

   HWND hWnd,

   L_UINT code,

   L_INT nZoom,

   LPRECT prcView,

   L_INT *pnHScroll,

   L_INT *pnVScroll

)

{

   SCROLLINFO si ;

  

  

   si.cbSize = sizeof (SCROLLINFO) ;

   si.fMask  = SIF_ALL ;

   GetScrollInfo (hWnd, SB_HORZ, &si) ;

  

   *pnHScroll = si.nPos ;

  

   switch ( code )

   {

   case SB_LINELEFT:   

      si.nPos -= 1 ;

      break ;

     

   case SB_LINERIGHT:  

      si.nPos += 1 ;

      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 ;

     

   default:

      break ;

   }

  

   si.fMask = SIF_POS ;

   SetScrollInfo (hWnd, SB_HORZ, &si, TRUE) ;

   GetScrollInfo (hWnd, SB_HORZ, &si) ;

  

   if ( si.nPos != *pnHScroll )

   {

      L_INT dxUpdate ;

     

     

      // update screen.

      if ( nZoom >= 100 )

      {

         dxUpdate = MulDiv ( ( *pnHScroll - si.nPos ), nZoom, 100 ) ;

      }

      else

      {

         dxUpdate = *pnHScroll - si.nPos ;

      }

     

      // update screen.

      OffsetRect ( prcView, dxUpdate, 0 ) ;

     

      ScrollWindow ( hWnd, dxUpdate, 0, NULL, NULL ) ;

      

      *pnHScroll = si.nPos ;

     

      UpdateWindow ( hWnd ) ;

   }

}

 

L_VOID OnVScroll

(

   HWND hWnd,

   L_UINT code,

   L_INT nZoom,

   LPRECT prcView,

   L_INT *pnHScroll,

   L_INT *pnVScroll

)

{

   SCROLLINFO si ;

  

  

   si.cbSize = sizeof ( SCROLLINFO ) ;

   si.fMask  = SIF_ALL ;

   GetScrollInfo (hWnd, SB_VERT, &si) ;

  

   *pnVScroll = si.nPos ;

  

   switch ( code )

   {

   case SB_LINEUP:

      si.nPos -= 1 ;

      break ;

     

   case SB_LINEDOWN:

      si.nPos += 1 ;

      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 ;

     

   default:

      break ;

   }

  

   si.fMask = SIF_POS ;

   SetScrollInfo ( hWnd, SB_VERT, &si, TRUE ) ;

   GetScrollInfo ( hWnd, SB_VERT, &si ) ;

  

   if ( si.nPos != *pnVScroll )

   {

      L_INT dyUpdate ;

     

     

      // update screen.

      if ( nZoom >= 100 )

      {

         dyUpdate = MulDiv ( ( *pnVScroll - si.nPos ), nZoom, 100 ) ;

      }

      else

      {

         dyUpdate = *pnVScroll - si.nPos ;

      }

     

      // update screen.

      OffsetRect ( prcView, 0, dyUpdate ) ;

     

      ScrollWindow ( hWnd, 0, dyUpdate, NULL, NULL ) ;

     

      *pnVScroll = si.nPos ;

     

      UpdateWindow ( hWnd ) ;

   }

}

 

L_VOID OnPaint

(

   HWND hWnd,

   pBITMAPHANDLE pBitmap,

   LPRECT prcView

)

{

   HDC hDC ;

   PAINTSTRUCT ps ;

   HPALETTE hOldPal = NULL;

   HPALETTE hPalette;

  

   hDC = BeginPaint (hWnd, &ps) ;

  

   if ( pBitmap->Flags.Allocated )

   {

      hPalette = L_CreatePaintPalette( hDC, pBitmap ) ;

      if ( hPalette )

      {

         hOldPal = SelectPalette ( hDC, hPalette, TRUE ) ;

         RealizePalette ( hDC ) ;

      }

     

      L_PaintDC( hDC, pBitmap, NULL, NULL, prcView, &ps.rcPaint, SRCCOPY ) ;

     

      if ( NULL != hOldPal )

      {

         SelectPalette ( hDC, hOldPal, TRUE ) ;

         DeleteObject(hPalette);

      }

   }

  

   EndPaint (hWnd, &ps) ;

}

 

 

static L_BOOL OnOpen ( HWND hWnd, pBITMAPHANDLE pBitmap )

{

   static L_INT  nOpenIndex = 0 ;

   OPENFILENAME  OpenFileName ;

   L_TCHAR        szFile [ MAX_PATH ] = TEXT("\0") ;

   L_TCHAR        szFileTitle [ MAX_PATH ] = TEXT("\0") ;

   L_TCHAR        szOpenFileFilter [ ] = {TEXT("ALL\0")TEXT("*.*\0")} ;

   OPENDLGPARAMS  FileOpenParams ;

   BITMAPHANDLE   hThumb ;

 

  

  

   memset ( &FileOpenParams, 0, sizeof ( OPENDLGPARAMS ) ) ;

  

   lstrcpy ( szFile, TEXT("") ) ;

  

   L_InitBitmap( pBitmap, sizeof(BITMAPHANDLE), 0, 0, 0 ) ;

  

   L_InitBitmap( &hThumb, sizeof(BITMAPHANDLE), 0, 0, 0 ) ;

  

   OpenFileName.lStructSize = sizeof(OPENFILENAME);

   OpenFileName.hwndOwner = hWnd;

   OpenFileName.lpstrFilter = szOpenFileFilter;

   OpenFileName.lpstrCustomFilter = NULL;

   OpenFileName.nMaxCustFilter = 0;

   OpenFileName.nFilterIndex = nOpenIndex;

   OpenFileName.nMaxFile = sizeof(szFile);

   OpenFileName.lpstrFile = szFile;

   OpenFileName.nMaxFileTitle = sizeof(szFileTitle);

   OpenFileName.lpstrFileTitle = szFileTitle;

   OpenFileName.lpstrInitialDir = NULL;

   OpenFileName.lpstrTitle = TEXT("Open a File");

   OpenFileName.nFileOffset = 0;

   OpenFileName.nFileExtension = 0;

   OpenFileName.lpstrDefExt = NULL;

   OpenFileName.lpfnHook = NULL;

   OpenFileName.Flags = OFN_LONGNAMES;

  

 

   FileOpenParams.uStructSize = sizeof(OPENDLGPARAMS);

   FileOpenParams.uDlgFlags =   DLG_OPEN_SHOW_PROGRESSIVE |

                           DLG_OPEN_SHOW_MULTIPAGE |

                           DLG_OPEN_SHOW_LOADROTATED |

                           DLG_OPEN_SHOW_LOADCOMPRESSED |

                           DLG_OPEN_SHOW_FILEINFO |

                           DLG_OPEN_SHOW_PREVIEW |

                           DLG_OPEN_ENABLESIZING |

                           DLG_OPEN_USEFILESTAMP |

                           DLG_OPEN_LOADBITMAP;

 

   if (L_DlgOpen( hWnd, &OpenFileName, &FileOpenParams) == SUCCESS_DLG_OK)

   {

      L_CopyBitmap(pBitmap, FileOpenParams.pFileData[0].pBitmap, sizeof(BITMAPHANDLE));

      L_FreeBitmap(FileOpenParams.pFileData[0].pBitmap);

      nOpenIndex = OpenFileName.nFilterIndex;

 

      L_FreeBitmap( &hThumb );

 

      L_ChangeBitmapViewPerspective(pBitmap, pBitmap, sizeof(BITMAPHANDLE), TOP_LEFT );

     

      return TRUE ;

   }

   else

   {

      return FALSE ;

   }

}

 

7.

Add the following lines in _tWinMain after  HACCEL hAccelTable;

 

  UNLOCKSUPPORT ( ) ;

  L_DlgInit(DLG_INIT_COLOR);

 

8.

In stdafx.h add the following headers: (keep in mind, you may have to change the path to where the header files reside):

 

#include <commdlg.h>

 

#include "..\..\..\..\..\Include\ltpnt.h"

#include "..\..\..\..\..\Include\l_bitmap.h"

#include "..\..\..\..\..\Include\ltdlg.h"

 

9.

Add the following code before the function "PostQuitMessage" call in the WM_DESTROY message in the WndProc function:

 

         if ( SUCCESS == L_PntIsValid ( pPaint ) )
         {
            L_PntFree ( pPaint ) ;
         }

 

10.

Create a new file called Imports.cpp in place it beside your project files.

 

In the Project Workspace, click the Solution Explorer tab.

 

Double-click the ToolbarTutorial folder to open it.

 

Right-click the Source files folder and select Add à New item.

 

Right-click on the Source file

 

Expand Visual C++ tree, if it is not already expanded.

 

Select Code from the sub tree.

 

Select C++ File (.cpp) from the right window.

 

In the name text box, specify Imports.

 

Click the OK button.

 

Double-click the Imports.cpp in the solution Explorer and add the following lines: (keep in mind, you may have to change the path to where the header files reside)

#include "StdAfx.h"

 

#if defined(FOR_WIN64)

   #pragma comment(lib, "..\\..\\..\\..\\..\\Lib\\CDLL\\x64\\Ltkrn_x.lib")

   #pragma comment(lib, "..\\..\\..\\..\\..\\Lib\\CDLL\\x64\\Ltdis_x.lib")

   #pragma comment(lib, "..\\..\\..\\..\\..\\Lib\\CDLL\\x64\\Ltdlgkrn_x.lib")

   #pragma comment(lib, "..\\..\\..\\..\\..\\Lib\\CDLL\\x64\\Ltdlgfile_x.lib")

   #pragma comment(lib, "..\\..\\..\\..\\..\\Lib\\CDLL\\x64\\Ltpnt_x.lib")

#elif defined(FOR_WIN32)

   #pragma comment(lib, "..\\..\\..\\..\\..\\Lib\\CDLL\\Win32\\Ltkrn_u.lib")

   #pragma comment(lib, "..\\..\\..\\..\\..\\Lib\\CDLL\\Win32\\Ltdis_u.lib")

   #pragma comment(lib, "..\\..\\..\\..\\..\\Lib\\CDLL\\Win32\\Ltdlgkrn_u.lib")

   #pragma comment(lib, "..\\..\\..\\..\\..\\Lib\\CDLL\\Win32\\Ltdlgfile_u.lib")

   #pragma comment(lib, "..\\..\\..\\..\\..\\Lib\\CDLL\\Win32\\Ltpnt_u.lib")

#endif // #if defined(FOR_WIN64)

 

11.

Compile and run the project by selecting Build->Execute tutorial.exe from the menu.