Announcement

Collapse
No announcement yet.

LoadBmp w/o using LoadImage

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • LoadBmp w/o using LoadImage

    Hi there,

    snippet below shows how to load a bitmap w/o using LoadImage.
    The BMP is display on the upper right of the dialog.

    There is a problem in WM_Paint :

    MEMCOPYD hMem + DATASTART, bm.bmBits, bm.bmWidthBytes * bm.bmHeight
    the destination is wrong ( bm.bmBits ). The image shifts left.

    Does anyone know why ?

    Ralph

    Code:
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    ' file : image.bas
    ' load bitmap from string
    '
    
    #DIM ALL
    #COMPILE EXE
    #INCLUDE "win32api.inc"
    
    
    FUNCTION MemCopyD(BYVAL src AS LONG, _
                      BYVAL dst AS LONG, _
                      BYVAL ln AS LONG) AS LONG
        #REGISTER NONE
          ! cld
          ! mov esi, src
          ! mov edi, dst
          ! mov ecx, ln
          ! shr ecx, 2
          ! rep movsd
          ! mov ecx, ln
          ! and ecx, 3
          ! rep movsb
        FUNCTION = 0
    END FUNCTION
    
    CALLBACK FUNCTION DlgMainProc
        STATIC hDisplay AS LONG
        STATIC hMem  AS LONG
        STATIC DataStart AS LONG
    
    
        SELECT CASE CBMSG
          CASE %WM_INITDIALOG
    
    '          LOCAL picFileName AS STRING
    '          picFileName = "E:\pbdll60\datalink\image\europa.bmp"
    '          hBmp = LoadImage(0, BYVAL STRPTR(picFileName), %IMAGE_BITMAP, 0, 0, %LR_LOADFROMFILE OR %LR_CREATEDIBSECTION )
              LOCAL hFile AS LONG
              LOCAL sBmp  AS STRING
              LOCAL bmf   AS BITMAPFILEHEADER PTR
    
              hFile = FREEFILE
              OPEN "E:\pbdll60\datalink\image\europa.bmp" FOR BINARY AS hFile
              sBmp = SPACE$( LOF( hFile ) )
              SEEK hFile, 1
              GET$ hFile, LOF( hFile ), sBmp
              CLOSE hFile
    
              bmf       = STRPTR( sBmp )
              DataStart = @bmf.bfOffBits
              hMem      = GlobalAlloc(%GMEM_FIXED , LEN ( sBmp ) - LEN( BITMAPFILEHEADER ) )
              MemCopyD  STRPTR(sBmp) + LEN( BITMAPFILEHEADER ), hMem, LEN( sBmp ) - LEN( BITMAPFILEHEADER )
    
          CASE %WM_DESTROY
              IF hMem THEN GlobalFree hMem
    
          CASE %WM_PAINT
            LOCAL hBmp      AS LONG
            LOCAL dcBitmap  AS LONG
            LOCAL bm        AS BITMAP
            LOCAL R         AS RECT
            LOCAL dcWindow  AS LONG
            LOCAL ps        AS PAINTSTRUCT
            LOCAL bmi       AS BITMAPINFO PTR
    
            GetClientRect  CBHNDL, r
            bmi = hMem
    
            BeginPaint CBHNDL, ps
    
               'Create DC - select bitmap
               dcWindow = GetDC(hDisplay)
               dcBitmap = CreateCompatibleDC(dcWindow)
               hBmp     = CreateDIBSection(dcBitmap, @bmi, %DIB_RGB_COLORS, 0, 0, 0)
    
               GlobalLock   hBmp
               SelectObject dcBitmap, hBmp
    
               'Get bitmap properties and destination size
               GetObject hBmp, SIZEOF(bm), bm
               MEMCOPYD hMem + DATASTART, bm.bmBits, bm.bmWidthBytes * bm.bmHeight
               BitBlt ps.hDC, 0, 0, r.nRight, r.nBottom, dcBitmap, 0, 0, %SRCCOPY
    
            EndPaint CBHNDL, ps
            EXIT FUNCTION
    
        END SELECT
    
    
    END FUNCTION
    
    FUNCTION PBMAIN()
       
        LOCAL hDlg AS LONG
        DIALOG NEW 0, "Load Bmp test", ,, 200, 300, %WS_CAPTION OR %WS_SYSMENU TO hDlg
        DIALOG SHOW MODAL hDlg, CALL DlgMainProc
    
    END FUNCTION

    ------------------

  • #2
    DataStart = @bmf.bfOffBits +1 ?

    ------------------
    Best Regards
    Peter Scheutz
    Best Regards
    Peter Scheutz

    Comment


    • #3
      Ralph --
      If bmi.bmiHeader.biBitCount <= 8 (256-colors), your code is simply incorrect, because there are additional fields.


      ------------------
      E-MAIL: [email protected]

      Comment


      • #4
        Peter,
        Semen,

        thanks for the reply. Fixed the bug.

        DataStart = @bmf.bfOffBits - LEN( BITMAPFILEHEADER )

        Ralph


        ------------------

        Comment


        • #5
          Semen,

          tried it with 16c, 256c, 24 bit and HighColor on NT4.
          No need to handle palette.

          rgds
          Ralph


          ------------------

          Comment


          • #6
            Ralph --
            > No need to handle palette.
            What do you mean ? That you use correct offset for DIB-section ?
            I tested visually only - yes, it looks so.
            But try your code in 256-colors video mode and you will see, that you should take "important colors", to build a palette and to select it into hDC.

            ------------------
            E-MAIL: [email protected]

            Comment


            • #7
              Semen,

              you make me curios. Tested it on 5 different PC's ( W95 to W2000 ).
              I know the code differs from MSDN or Borland samples but it works.
              Even displays HiColor BMPs on 256 Color Desktop.
              It GPF's on opening non existing BMP files.
              If someone has problems displaying BMPs pls let me know.

              rgds
              Ralph

              ------------------

              Comment


              • #8
                Semen found a bug !

                If window colors are set to 256 and the number of colors used
                in bmp between 17 and 256 then the colors are displayed wrong.
                To fix it you'll have to use something like that:

                Code:
                ( c - sample )
                int nColors = bmInfo.bmiHeader.biClrUsed ? bmInfo.bmiHeader.biClrUsed :
                						1 << bmInfo.bmiHeader.biBitCount;
                
                	// Create the palette
                	if( nColors <= 256 )
                	{
                		UINT nSize = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * nColors);
                		LOGPALETTE *pLP = (LOGPALETTE *) new BYTE[nSize];
                
                		pLP->palVersion = 0x300;
                		pLP->palNumEntries = nColors;
                
                		for( int i=0; i < nColors; i++)
                		{
                			pLP->palPalEntry[i].peRed = bmInfo.bmiColors[i].rgbRed;
                			pLP->palPalEntry[i].peGreen = bmInfo.bmiColors[i].rgbGreen;
                			pLP->palPalEntry[i].peBlue = bmInfo.bmiColors[i].rgbBlue;
                			pLP->palPalEntry[i].peFlags = 0;
                		}
                
                		pPal->CreatePalette( pLP );
                
                		delete[] pLP;
                	}



                ------------------

                Comment


                • #9
                  I reconstructed Ralph's code a little to support a palette in 256-colors bmp.
                  Tested with one bmp only

                  Code:
                      #Compile Exe
                      #Register None
                      #Dim All
                      #Include "Win32Api.Inc"
                  
                      $BmpFile = "C:\Bmp\Bmp1.Bmp" ' <------- Change
                  
                      CallBack Function DlgProc
                         Dim bmf As BITMAPFILEHEADER Ptr, bmi As BITMAPINFO Ptr
                         Dim hMemDC As Long, hMemBmp As Long, hFile As Long
                         Dim ps As PAINTSTRUCT, rc As RECT, bm As BitMap
                         Dim sBmp As Static String, hPalette As Static Long
                  
                         Select Case CbMsg
                            Case %WM_PAINT
                               If sBmp = "" Then hFile = FreeFile: Open $BmpFile For Binary As hFile: _
                                  If Err = 0 Then Get$ hFile, Lof(hFile), sBmp: Close #hFile
                               If sBmp = "" Then Exit Function
                  
                               bmf = StrPtr(sBmp)
                               bmi = bmf + Len(BITMAPFILEHEADER)
                  
                               If @bmi.bmiHeader.biBitCount = 8  Then ' for 256
                                  hPalette = @bmi.bmiHeader.biClrUsed
                                  If hPalette = 0 Then hPalette = 256
                                  @bmi.bmiHeader.biClrImportant = MakLng(&H300, hPalette)
                                  hPalette = CreatePalette (ByVal VarPtr(@bmi.bmiHeader.biClrImportant))
                               End If
                  
                               BeginPaint CbHndl, ps
                               hMemDC   = CreateCompatibleDC(ps.hDC)
                               hMemBmp  = CreateDIBSection(hMemDC, @bmi, %DIB_RGB_COLORS, 0, 0, 0)
                               GlobalLock hMemBmp: SelectObject hMemDC, hMemBmp
                               GetObject hMemBmp, SizeOf(bm), bm
                  
                               MoveMemory bm.bmBits, StrPtr(sBmp) + @bmf.bfOffBits, bm.bmWidthBytes * bm.bmHeight
                               
                               If hPalette Then Selectpalette ps.hDC, hPalette, %False: RealizePalette ps.hDC
                  
                               GetClientRect  CbHndl, rc
                               BitBlt ps.hDC, rc.nLeft, rc.nTop, rc.nRight - rc.nLeft, rc.nBottom - rc.nTop, hMemDC, 0, 0, %SRCCOPY
                               EndPaint CbHndl, ps
                               DeleteDC hMemDC: DeleteObject hMemBmp
                  
                            Case %WM_QUERYNEWPALETTE
                               If hPalette Then
                                  ps.hDC = GetDC(CbHndl)
                                  SelectPalette ps.hDC, hPalette, %FALSE
                                  RealizePalette ps.hDC
                                  InvalidateRect CbHndl, ByVal 0, 1
                                  ReleaseDC CbHndl, ps.hDC
                                  Function = 1
                               End If
                  
                           Case %WM_PALETTECHANGED
                              If hPalette And (CbWparam <> CbHndl) Then
                                 ps.hDC = GetDC(CbHndl)
                                 SelectPalette ps.hDC, hPalette, %FALSE
                                 RealizePalette ps.hDC
                                 UpdateColors ps.hDC
                                 ReleaseDC CbHndl, ps.hDC
                              End If
                          
                          Case %WM_DESTROY
                               If hPalette Then DeleteObject hPalette
                         End Select
                      End Function
                  
                      Function PbMain
                         Local hDlg As Long
                         Dialog New 0, "Load Bmp test", ,, 200, 300, %WS_CAPTION Or %WS_SYSMENU To hDlg
                         Dialog Show Modal hDlg Call DlgProc
                     End Function
                  ------------------
                  E-MAIL: [email protected]

                  [This message has been edited by Semen Matusovski (edited April 10, 2001).]

                  Comment


                  • #10
                    Originally posted by Semen Matusovski:
                    I reconstructed Ralph's code a little to support a palette in 256-colors bmp.
                    Tested with one bmp only

                    Why no Selectobject(hMemDC, OldhMemBmp) and DeleteObject hMemBmp?
                    Sure that is handled by Windows?



                    ------------------
                    Best Regards
                    Peter Scheutz
                    Best Regards
                    Peter Scheutz

                    Comment


                    • #11
                      Peter --
                      I was interesting to find an offset and didn't test initial code in general.
                      I added DeleteDC hMemDC: DeleteObject hMemBmp after EndPaint (when there is no memory hDC, it's possible to delete bitmap handle)


                      ------------------
                      E-MAIL: [email protected]

                      Comment


                      • #12
                        Semen,

                        thanks for the sample.
                        Added some changes to your code to seperate create and draw.

                        Ralph

                        Code:
                        #COMPILE EXE
                        #REGISTER NONE
                        #DIM ALL
                        #INCLUDE "Win32Api.Inc"
                        
                        $BmpFile = "Bmp1.Bmp" ' <------- Change
                        
                        FUNCTION MemCopyD(BYVAL src AS LONG, _
                                          BYVAL dst AS LONG, _
                                          BYVAL ln AS LONG) AS LONG
                            #REGISTER NONE
                              ! cld
                              ! mov esi, src
                              ! mov edi, dst
                              ! mov ecx, ln
                              ! shr ecx, 2
                              ! rep movsd
                              ! mov ecx, ln
                              ! and ecx, 3
                              ! rep movsb
                            FUNCTION = 0
                        END FUNCTION
                        
                        CALLBACK FUNCTION DlgProc
                        
                           STATIC hPalette AS LONG
                           STATIC hBmp     AS LONG
                        
                           SELECT CASE CBMSG
                        
                             CASE %WM_INITDIALOG
                        
                                 LOCAL hFile    AS LONG
                                 LOCAL dcWindow AS LONG
                                 LOCAL dcBitmap AS LONG
                                 LOCAL bmf      AS BITMAPFILEHEADER PTR
                                 LOCAL bmi      AS BITMAPINFO PTR
                                 LOCAL bm       AS BitMap
                                 LOCAL sBmp     AS STRING
                        
                                 hFile = FREEFILE
                                 OPEN $BmpFile FOR BINARY AS hFile
                                 IF ERR = 0 THEN
                                    GET$ hFile, LOF(hFile), sBmp
                                 END IF
                                 CLOSE #hFile
                                 IF sBmp = "" THEN EXIT FUNCTION
                        
                                 bmf = STRPTR(sBmp)
                                 bmi = bmf + LEN(BITMAPFILEHEADER)
                                 IF @bmi.bmiHeader.biBitCount = 8  THEN
                                    hPalette = @bmi.bmiHeader.biClrUsed
                                    IF hPalette = 0 THEN hPalette = 256
                                    @bmi.bmiHeader.biClrImportant = MAKLNG(&H300, hPalette)
                                    hPalette = CreatePalette (BYVAL VARPTR(@bmi.bmiHeader.biClrImportant))
                                 END IF
                        
                                 dcWindow = GetDC( %Hwnd_desktop )
                                 dcBitmap = CreateCompatibleDC(dcWindow)
                                 hBmp     = CreateDIBSection(dcBitmap, @bmi, %DIB_RGB_COLORS, 0, 0, 0)
                        
                                 GlobalLock   hBmp
                                 SelectObject dcBitmap, hBmp
                                 GetObject    hBmp, SIZEOF(bm), bm
                                 MemCopyD     STRPTR(sBmp) + @bmf.bfOffBits, bm.bmBits, bm.bmWidthBytes * bm.bmHeight
                                 DeleteDC     dcBitmap
                                 ReleaseDC    %Hwnd_desktop, dcWindow
                        
                             CASE %WM_PAINT
                        
                                 LOCAL hMemDC AS LONG
                                 LOCAL ps     AS PAINTSTRUCT
                                 LOCAL rc     AS RECT
                        
                                 GetClientRect CBHNDL, rc
                                 BeginPaint CBHNDL, ps
                                    IF hBmp THEN
                                        hMemDC = CreateCompatibleDC(ps.hDC)
                                        SelectObject hMemDC, hBmp
                                        IF hPalette THEN
                                           Selectpalette  ps.hDC, hPalette, %False
                                           RealizePalette ps.hDC
                                        END IF
                                        BitBlt ps.hDC, rc.nLeft, rc.nTop, rc.nRight - rc.nLeft, rc.nBottom - rc.nTop, hMemDC, 0, 0, %SRCCOPY
                                        DeleteDC hMemDC
                                    END IF
                                 EndPaint CBHNDL, ps
                        
                             CASE %WM_QUERYNEWPALETTE
                                 IF hPalette THEN
                                    ps.hDC = GetDC(CBHNDL)
                                    SelectPalette ps.hDC, hPalette, %FALSE
                                    RealizePalette ps.hDC
                                    InvalidateRect CBHNDL, BYVAL 0, 1
                                    ReleaseDC CBHNDL, ps.hDC
                                    FUNCTION = 1
                                 END IF
                        
                             CASE %WM_PALETTECHANGED
                                 IF hPalette AND (CBWPARAM <> CBHNDL) THEN
                                    ps.hDC = GetDC(CBHNDL)
                                    SelectPalette  ps.hDC, hPalette, %FALSE
                                    RealizePalette ps.hDC
                                    UpdateColors   ps.hDC
                                    ReleaseDC CBHNDL, ps.hDC
                                 END IF
                        
                             CASE %WM_DESTROY
                                  IF hPalette THEN DeleteObject hPalette
                                  IF hBmp     THEN DeleteObject hBmp
                        
                           END SELECT
                        
                        END FUNCTION
                        
                        FUNCTION PBMAIN
                        
                            LOCAL hDlg AS LONG
                            DIALOG NEW 0, "Load Bmp test", ,, 200, 300, %WS_CAPTION OR %WS_SYSMENU TO hDlg
                            DIALOG SHOW MODAL hDlg CALL DlgProc
                        
                        END FUNCTION
                        _


                        ------------------

                        Comment


                        • #13
                          Code:
                               CASE %WM_PAINT
                          
                                   LOCAL hMemDC AS LONG
                                   LOCAL ps     AS PAINTSTRUCT
                                   LOCAL rc     AS RECT
                                   LOCAL oldhBmp AS LONG
                          
                                   GetClientRect CBHNDL, rc
                                   BeginPaint CBHNDL, ps
                                      IF hBmp THEN
                                          hMemDC = CreateCompatibleDC(ps.hDC)
                                          oldhBmp = SelectObject(hMemDC, hBmp)
                                          IF hPalette THEN
                                             Selectpalette  ps.hDC, hPalette, %False
                                             RealizePalette ps.hDC
                                          END IF
                                          BitBlt ps.hDC, rc.nLeft, rc.nTop, rc.nRight - rc.nLeft, rc.nBottom - rc.nTop, hMemDC, 0, 0, %SRCCOPY
                                          SelectObject hMemDC, oldhBmp
                                          DeleteDC hMemDC
                                      END IF
                                   EndPaint CBHNDL, ps
                          _

                          I still think the above code is needed to prevent memory leaks.


                          ------------------
                          Best Regards
                          Peter Scheutz
                          Best Regards
                          Peter Scheutz

                          Comment


                          • #14
                            Peter --
                            In WM_PAINT Ralph create and delete memory DC. Check return code for DeleteDC.
                            Where memory leaks ?

                            oldhBmp = SelectObject(hMemDC, hBmp)
                            ...
                            SelectObject hMemDC, oldhBmp

                            are used, when it's necessary to release bitmap handle before deleting memdc.
                            After - too late, hBmp already free.

                            ------------------
                            E-MAIL: [email protected]

                            Comment


                            • #15
                              Semen--

                              I may very well be wrong.
                              It's just that most code I have seen always seem to deselect objects from DC's before deleting or releasing them(the DC's).
                              It seems good coding practice.
                              Otherwise I think one should at least check the return value from the DeleteDC function?

                              ------------------
                              Best Regards
                              Peter Scheutz

                              [This message has been edited by Peter Scheutz (edited April 10, 2001).]
                              Best Regards
                              Peter Scheutz

                              Comment


                              • #16
                                Hi there,

                                thanks for all the help. Here's my final version :

                                Code:
                                ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
                                ' file : paintbox.bas
                                '
                                
                                '''''''''
                                ' return Hbmp & hPalette
                                '
                                %LR_LOADFROMSTRING = -1
                                
                                FUNCTION BMPload( BYVAL sBmp AS STRING, BYVAL flag AS LONG, hPalette AS LONG ) AS LONG
                                
                                     LOCAL hFile    AS LONG
                                     LOCAL dcWindow AS LONG
                                     LOCAL dcBitmap AS LONG
                                     LOCAL bmf      AS BITMAPFILEHEADER PTR
                                     LOCAL bmi      AS BITMAPINFO PTR
                                     LOCAL bm       AS BitMap
                                     LOCAL hBmp     AS LONG
                                
                                
                                     SELECT CASE flag
                                       CASE %LR_LOADFROMFILE
                                         hFile = FREEFILE
                                         OPEN sBmp FOR BINARY AS hFile
                                         IF ERR = 0 THEN GET$ hFile, LOF(hFile), sBmp
                                         CLOSE #hFile
                                
                                       CASE %LR_LOADFROMSTRING
                                
                                       CASE ELSE
                                         MSGBOX "Invalid flag. Pls use %LR_LOADFROMFILE or %LR_LOADFROMSTRING", %MB_ICONSTOP, "loadBmp"
                                         EXIT FUNCTION
                                     END SELECT
                                
                                     IF sBmp = "" THEN EXIT FUNCTION
                                     IF LEN( sBmp ) < ( LEN(BITMAPFILEHEADER) + LEN( BITMAPINFO ) ) THEN EXIT FUNCTION
                                
                                     bmf = STRPTR(sBmp)
                                     bmi = bmf + LEN(BITMAPFILEHEADER)
                                     IF @bmi.bmiHeader.biBitCount = 8  THEN
                                        hPalette = @bmi.bmiHeader.biClrUsed
                                        IF hPalette = 0 THEN hPalette = 256
                                        @bmi.bmiHeader.biClrImportant = MAKLNG(&H300, hPalette)
                                        hPalette = CreatePalette (BYVAL VARPTR(@bmi.bmiHeader.biClrImportant))
                                     END IF
                                
                                     dcWindow = GetDC( %Hwnd_desktop )
                                     dcBitmap = CreateCompatibleDC(dcWindow)
                                     hBmp     = CreateDIBSection(dcBitmap, @bmi, %DIB_RGB_COLORS, 0, 0, 0)
                                     GlobalLock   hBmp
                                     SelectObject dcBitmap, hBmp
                                     GetObject    hBmp, SIZEOF(bm), bm
                                     MemCopyD     STRPTR(sBmp) + @bmf.bfOffBits, bm.bmBits, bm.bmWidthBytes * bm.bmHeight
                                     DeleteDC     dcBitmap
                                     ReleaseDC    %Hwnd_desktop, dcWindow
                                
                                     FUNCTION = hBmp
                                
                                END FUNCTION
                                
                                
                                SUB BMPunLoad ( hBmp AS LONG, hPalette AS LONG )
                                    IF hPalette THEN DeleteObject hPalette : hPalette = %NULL
                                    IF hBmp     THEN DeleteObject hBmp     : hBmp = %NULL
                                END SUB
                                
                                
                                SUB BMPsetPalette( BYVAL hDC AS LONG, BYVAL hPalette AS LONG )
                                    IF ISFALSE hPalette THEN EXIT SUB
                                    SelectPalette  hDC, hPalette, %FALSE
                                    RealizePalette hDC
                                END SUB
                                
                                
                                FUNCTION BMPcheckPalette( BYVAL hWnd AS LONG, BYVAL wMsg AS LONG, BYVAL wParam AS LONG, BYVAL hPalette AS LONG ) AS LONG
                                    LOCAL hdc AS LONG
                                
                                    IF ISFALSE hPalette THEN EXIT FUNCTION
                                    IF ( wMsg = %WM_PALETTECHANGED ) AND ( WPARAM = hWnd ) THEN EXIT FUNCTION
                                    hDC = GetDC( hWnd )
                                    BMPsetPalette hDC, hPalette
                                    IF wMsg = %WM_PALETTECHANGED THEN
                                       UpdateColors   hDC
                                    ELSE
                                       InvalidateRect hWnd, BYVAL 0, 1
                                       FUNCTION = 1
                                    END IF
                                    ReleaseDC hWnd, hDC
                                
                                END FUNCTION
                                
                                
                                %BMPDraw_KeepRatio = 1
                                %BMPDraw_FitToWin  = 2
                                %BMPDraw_KeepSize  = 4
                                
                                FUNCTION BMPDraw( BYVAL hdc AS LONG, BYVAL hBmp AS LONG, BYVAL hPalette AS LONG, r AS rect, drwFlag AS LONG ) AS LONG
                                
                                    IF ISFALSE hdc  THEN EXIT FUNCTION
                                    FillRect hdc, r, GetStockObject(%GRAY_BRUSH)      ' CLS
                                    IF ISFALSE hBmp THEN EXIT FUNCTION
                                    
                                    LOCAL bm     AS BITMAP
                                    LOCAL AspX   AS SINGLE
                                    LOCAL AspY   AS SINGLE
                                    LOCAL Xpos   AS LONG
                                    LOCAL Ypos   AS LONG
                                    LOCAL hMemDC AS LONG
                                    
                                    
                                    
                                    hMemDC = CreateCompatibleDC( hdc )
                                    SelectObject  hMemDC, hBmp
                                    BMPsetPalette hdc, hPalette
                                
                                    SELECT CASE drwFlag
                                       CASE %BMPDraw_KeepRatio                              ' Zoom to Window
                                          GetObject     hBmp, SIZEOF(bm), bm
                                          AspX = R.nRight  / bm.bmWidth
                                          AspY = R.nBottom / bm.bmHeight
                                          IF AspX > AspY THEN AspX = AspY
                                          IF AspX > 1 THEN Xpos = ((R.nRight -  bm.bmWidth)  / 2) - (((bm.bmWidth  * AspX) - bm.bmWidth)  / 2)
                                          IF AspY > 1 THEN Ypos = ((R.nBottom - bm.bmHeight) / 2) - (((bm.bmHeight * AspX) - bm.bmHeight) / 2)
                                          IF Xpos < 0 THEN Xpos = 0
                                          IF Ypos < 0 THEN Ypos = 0
                                          StretchBlt hdc, Xpos, Ypos, bm.bmWidth * AspX, bm.bmHeight * AspX, hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, %SRCCOPY
                                        
                                       CASE %BMPDraw_FitToWin                               ' center or display upper left
                                          GetObject     hBmp, SIZEOF(bm), bm
                                          AspX = 1 : AspY = 1
                                          IF bm.bmWidth  > R.nRight  THEN AspX = R.nRight / bm.bmWidth
                                          IF bm.bmHeight > R.nBottom THEN AspY = R.nBottom / bm.bmHeight
                                          IF bm.bmWidth  < R.nRight  THEN Xpos = (R.nRight  - bm.bmWidth)  / 2 * AspX
                                          IF bm.bmHeight < R.nBottom THEN Ypos = (R.nBottom - bm.bmHeight) / 2 * AspY
                                          BitBlt hdc, Xpos, Ypos, bm.bmWidth * AspX, bm.bmHeight * AspY, hMemDC, 0, 0, %SRCCOPY
                                
                                       CASE %BMPDraw_KeepSize
                                          BitBlt hdc, r.nLeft, r.nTop, r.nRight - r.nLeft, r.nBottom - r.nTop, hMemDC, 0, 0, %SRCCOPY
                                          
                                       CASE ELSE
                                          BitBlt hdc, r.nLeft, r.nTop, r.nRight - r.nLeft, r.nBottom - r.nTop, hMemDC, 0, 0, %SRCCOPY
                                          
                                     END SELECT
                                
                                     DeleteDC      hMemDC
                                
                                END FUNCTION
                                ------------------

                                Comment


                                • #17
                                  Sample app for paintbox.bas

                                  rgds
                                  Ralph

                                  Code:
                                  #COMPILE EXE
                                  #REGISTER NONE
                                  #DIM ALL
                                  #INCLUDE "Win32Api.Inc"
                                  
                                  ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
                                  ' from Steve Hutchesson
                                  FUNCTION MemCopyD(BYVAL src AS LONG, _
                                                    BYVAL dst AS LONG, _
                                                    BYVAL ln AS LONG) AS LONG
                                      #REGISTER NONE
                                        ! cld
                                        ! mov esi, src
                                        ! mov edi, dst
                                        ! mov ecx, ln
                                        ! shr ecx, 2
                                        ! rep movsd
                                        ! mov ecx, ln
                                        ! and ecx, 3
                                        ! rep movsb
                                      FUNCTION = 0
                                  END FUNCTION
                                  
                                  '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
                                  ' bitmap converted from file to string with file2asm from Steve Hutchesson
                                  FUNCTION europa_bmp() AS STRING
                                  
                                    ' E:\PBDLL60\datalink\image\Europa.bmp 2518 bytes(decimal)
                                  
                                    ! jmp end_A3C535
                                  
                                  start_A3C535:
                                    ! db 66,77,214,9,0,0,0,0,0,0,54,4,0,0,40,0
                                    ! db 0,0,46,0,0,0,30,0,0,0,1,0,8,0,0,0
                                    ! db 0,0,160,5,0,0,0,0,0,0,0,0,0,0,0,1
                                    ! db 0,0,0,0,0,0,0,0,0,0,0,0,128,0,0,128
                                    ! db 0,0,0,128,128,0,128,0,0,0,128,0,128,0,128,128
                                    ! db 0,0,128,128,128,0,192,192,192,0,0,0,255,0,0,255
                                    ! db 0,0,0,255,255,0,255,0,0,0,255,0,255,0,255,255
                                    ! db 0,0,255,255,255,0,240,42,59,0,121,88,119,0,160,0
                                    ! db 23,0,0,18,239,0,0,0,1,0,231,158,0,0,136,0
                                    ! db 65,0,0,18,239,0,18,240,95,0,255,176,0,0,72,0
                                    ! db 18,0,119,243,176,0,243,206,56,0,255,255,119,0,1,255
                                    ! db 255,0,0,0,0,0,67,246,232,0,125,152,0,0,184,0
                                    ! db 23,0,0,18,248,0,0,0,102,0,121,88,0,0,66,0
                                    ! db 23,0,1,125,2,0,23,123,136,0,0,1,0,0,152,0
                                    ! db 0,0,0,23,125,0,0,0,76,0,2,66,0,0,0,1
                                    ! db 125,0,0,64,0,0,23,125,152,0,0,0,0,0,0,0
                                    ! db 0,0,0,0,0,0,0,0,1,0,124,140,0,0,4,0
                                    ! db 23,0,0,0,1,0,0,0,0,0,0,0,0,0,136,0
                                    ! db 0,0,0,23,123,0,18,240,44,0,0,108,0,0,8,0
                                    ! db 8,0,0,15,0,0,0,0,0,0,121,88,0,0,192,0
                                    ! db 23,0,0,64,115,0,72,2,220,0,112,79,0,0,101,110
                                    ! db 101,0,0,0,110,0,23,126,32,0,11,228,0,0,1,119
                                    ! db 226,0,0,0,0,0,0,0,0,0,124,88,0,0,58,0
                                    ! db 23,0,119,225,31,0,92,58,67,0,77,69,84,0,69,0
                                    ! db 80,0,111,114,117,0,46,97,112,0,112,109,98,0,6,0
                                    ! db 0,0,0,0,0,0,18,241,172,0,0,1,0,0,232,0
                                    ! db 0,0,0,18,241,0,21,255,236,0,3,32,0,0,6,0
                                    ! db 133,0,0,0,0,0,21,252,208,0,0,0,0,0,0,0
                                    ! db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,196,0
                                    ! db 0,0,0,18,241,0,237,32,102,0,3,32,119,0,208,0
                                    ! db 133,0,0,21,252,0,18,241,236,0,0,6,0,0,124,0
                                    ! db 0,0,119,237,32,0,239,103,192,0,0,6,119,0,80,0
                                    ! db 0,0,0,18,243,0,0,0,6,0,0,2,0,0,124,0
                                    ! db 0,0,119,237,32,0,239,103,192,0,0,2,119,0,104,0
                                    ! db 0,0,0,18,243,0,0,0,2,0,235,252,0,0,248,127
                                    ! db 253,0,127,253,235,0,18,241,36,0,176,207,0,0,0,119
                                    ! db 246,0,0,0,0,0,18,241,36,0,177,53,0,0,136,119
                                    ! db 246,0,0,20,9,0,0,0,0,0,235,248,0,0,244,127
                                    ! db 253,0,119,222,240,0,20,9,136,0,0,12,0,0,200,0
                                    ! db 13,0,119,229,127,0,0,0,80,0,241,172,0,0,8,0
                                    ! db 18,0,0,18,243,0,1,0,68,0,176,207,1,0,24,119
                                    ! db 246,0,0,0,1,0,231,21,65,0,2,66,119,0,32,1
                                    ! db 125,0,0,0,0,0,23,121,80,0,0,40,0,0,88,0
                                    ! db 20,0,0,23,121,0,0,2,158,0,1,32,0,0,200,0
                                    ! db 0,0,0,86,186,0,20,2,0,0,4,184,0,0,67,0
                                    ! db 22,0,84,92,58,0,80,77,69,0,117,69,92,0,112,111
                                    ! db 114,0,98,46,97,0,0,112,109,0,254,148,0,0,64,119
                                    ! db 248,0,119,249,179,0,255,255,255,0,242,8,255,0,28,0
                                    ! db 18,0,119,246,75,0,20,0,0,0,0,8,0,0,24,0
                                    ! db 5,0,0,0,1,0,0,0,102,0,0,8,0,0,66,0
                                    ! db 0,0,1,125,2,0,0,0,12,0,0,0,0,0,232,0
                                    ! db 0,0,0,18,241,0,21,255,236,0,0,3,0,0,6,0
                                    ! db 0,0,0,0,0,0,18,243,16,0,83,64,0,0,68,112
                                    ! db 255,0,1,1,0,0,18,241,232,0,255,236,0,0,68,0
                                    ! db 21,0,1,1,0,0,0,0,0,0,242,236,0,0,77,0
                                    ! db 18,0,119,237,49,0,1,0,68,0,241,236,1,0,6,0
                                    ! db 18,0,0,0,0,0,18,243,32,0,0,1,0,0,92,0
                                    ! db 0,0,0,18,243,0,21,255,236,0,0,68,0,0,71,1
                                    ! db 1,0,101,114,101,0,86,100,101,0,33,153,0,0,96,0
                                    ! db 69,0,0,18,242,0,0,0,47,0,0,51,0,0,232,0
                                    ! db 0,0,0,18,244,0,18,242,84,0,40,243,0,0,0,119
                                    ! db 240,0,0,20,0,0,5,0,8,0,1,24,0,0,102,0
                                    ! db 0,0,0,0,0,0,0,0,102,0,2,66,0,0,0,1
                                    ! db 125,0,0,0,0,0,0,0,0,0,32,102,0,0,96,119
                                    ! db 237,0,0,133,9,0,21,252,208,0,242,28,0,0,31,0
                                    ! db 18,0,0,0,0,0,18,255,176,0,176,72,0,0,200,119
                                    ! db 243,0,119,243,205,0,255,255,255,0,136,229,255,0,66,0
                                    ! db 67,0,1,125,2,0,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,0,0,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,0,0,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,4,4,4,4,4,4,11,11,4,4
                                    ! db 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,0,0,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,4,4,4,4,4,4,11,11,4,4
                                    ! db 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,0,0,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,11,11,4,4,4,4,4,4,4,4
                                    ! db 4,4,11,11,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,0,0,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,11,11,4,4,4,4,4,4,4,4
                                    ! db 4,4,11,11,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,0,0,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,0,0,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,0,0,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,11,11,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,11,11,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,0,0,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,11,11,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,11,11,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,0,0,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,0,0,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,0,0,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,0,0,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,0,0,4,4,4,4,4,4,4,4,4,11
                                    ! db 11,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,4,4,11,11,4,4,4,4,4,4
                                    ! db 4,4,4,4,0,0,4,4,4,4,4,4,4,4,4,11
                                    ! db 11,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,4,4,11,11,4,4,4,4,4,4
                                    ! db 4,4,4,4,0,0,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,0,0,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,0,0,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,0,0,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,0,0,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,11,11,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,11,11,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,0,0,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,11,11,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,11,11,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,0,0,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,0,0,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,0,0,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,0,0,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,11,11,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,11,11,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,0,0,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,11,11,4,4,4,4,4,11,11,4,4
                                    ! db 4,4,11,11,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,0,0,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,4,4,4,4,4,4,11,11,4,4
                                    ! db 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,0,0,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,0,0,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
                                    ! db 4,4,4,4,0,0
                                  end_A3C535:
                                  
                                      LOCAL Dest AS STRING
                                      Dest = SPACE$(2518)
                                  
                                        ! mov ecx, 2518
                                        ! cld
                                        ! lea esi, start_A3C535
                                        ! mov edi, dest
                                        ! rep movsb
                                  
                                      FUNCTION = Dest
                                  
                                  END FUNCTION
                                  
                                  #INCLUDE "paintBox.bas"
                                  
                                  CALLBACK FUNCTION DlgProc
                                  
                                     STATIC hPalette AS LONG
                                     STATIC hBmp     AS LONG
                                     LOCAL  rc       AS RECT
                                     
                                     SELECT CASE CBMSG
                                  
                                       CASE %WM_INITDIALOG          : hBmp = BMPload ( europa_bmp(), %LR_LOADFROMSTRING , hPalette )  '' load from string
                                                                    '  hBmp = BMPload ( "Bmp1.Bmp", %LR_LOADFROMFILE, hPalette )       '' load from file
                                       CASE %WM_SIZE
                                            IF CBWPARAM <> %SIZE_MINIMIZED THEN
                                               GetClientRect  CBHNDL, rc
                                               InvalidateRect CBHNDL, BYVAL 0, 1
                                            END IF
                                           
                                       CASE %WM_PAINT
                                           LOCAL ps AS PAINTSTRUCT
                                           GetClientRect CBHNDL, rc
                                           BeginPaint    CBHNDL, ps
                                           BMPDraw       ps.hDC, hBmp, hPalette, rc, %BMPDraw_FitToWin  '' %BMPDraw_FitToWin, %BMPDraw_KeepSize, %BMPDraw_KeepRatio
                                           EndPaint      CBHNDL, ps
                                  
                                       CASE %WM_QUERYNEWPALETTE, _
                                            %WM_PALETTECHANGED      : FUNCTION = BMPcheckPalette( CBHNDL, CBMSG, CBWPARAM, hPalette )
                                       CASE %WM_ERASEBKGND          : FUNCTION = %TRUE : EXIT FUNCTION
                                       CASE %WM_DESTROY             : BMPunLoad hBmp, hPalette
                                  
                                     END SELECT
                                  
                                  END FUNCTION
                                  
                                  FUNCTION PBMAIN
                                  
                                      LOCAL hDlg AS LONG
                                      DIALOG NEW 0, "Load Bmp test", ,, 200, 300, %WS_CAPTION OR %WS_SYSMENU OR %WS_THICKFRAME TO hDlg
                                      DIALOG SHOW MODAL hDlg CALL DlgProc
                                  
                                  END FUNCTION
                                  _




                                  ------------------

                                  Comment

                                  Working...
                                  X