- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I am trying to create several bitmaps, draw graphs, output text, etc in them and then bitblt them onto the screen. My code follows but it does no work. Any help will be much appreciated. Brooks V.
In WinMainProc...
case (WM_CREATE)
hDC = BeginPaint(hWndMain,lppaint)
hDCMem1 = CreateCompatibleDC(hDC)
hBM1 = CreateCompatibleBitMap(hDCMem1,maxx, maxy)
hTemp = SelectObject(hDCMem1, hBM1)
hOldPen = SelectObject (hDCMem1,hPen)
hDCMem2 = CreateCompatibleDC(hDC)
hBM2 = CreateCompatibleBitMap(hDCMem2,maxx, maxy)
hTemp = SelectObject(hDCMem2, hBM2)
hOldPen = SelectObject (hDCMem2,hPen)
bret = EndPaint(hWndMain,lppaint)
Later in the sequence of things...
case (WM_PAINT)
hDC = BeginPaint(hWndMain,lppaint)
nx = Rectxy%right - Rectxy%left
ny = Rectxy%bottom - Rectxy%top
Select Case (myOption)
case (1)
bret = BitBlt (hdc, 0, 0, nx, ny, hBM1, 0, 0, SRCCOPY)
case (2)
bret = BitBlt (hdc, 0, 0, nx, ny, hBM2, 0, 0, SRCCOPY)
End Select
bret = EndPaint(hWndMain,lppaint)
Then in a button callback
if (myOpt == 1) Then
hBM = hBM1
else
hBM = hBM2
end if
bret = MoveToEx(hBM, x, y, NULL)
do i = 1, 50
x = ptx(i)
y = PtY(i)
bret = LineTo(hBM, x, y)
end do
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I no longer use Quickwin but I used to use it a lot and you can have modeless dialogs. I recall then documentation was a bit misleading on this subject. Have you verified that the bitmap structure that you are pointing at is valid?
I have not quite worked out what you are trying to do. is it capture a window data as a bmp, and repaint it adding some more graphic elements on top?
Did you look at http://msdn.microsoft.com/en-us/library/windows/desktop/dd183402(v=vs.85).aspx
I have my own working fortrainised version of that if it helps....
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You might want to take a look at the SCIGRAPH sample in the QuickWin.zip sample collection installed along with the compiler.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I did but it does appear to be the same. They use MDI rather than SDI architecture. But I will look again.
Thanks,
Brooks V
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Sorry, that was doesn't and not does. Brooks V
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I generate data in fortran applications but the Windows interfaces, graphs etc. are developed using C++.
Probably would be more convenient to use OpenGL for creating graphs in Fortran.
You can also browse www.codeproject.com where you can find a very huge amount of cases and samples.
Regards
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Since you want bitmap graphs, you might also consider a Quickwin project. This gives you access to powerful primitive graphics functions, similar (but different) from the Windows functions you showed. The advantage over SciGraph or other 3rd party libraries is that you have complete control over every detail of your graph. The disadvantage is that you have to take control over every detail of your graph. Another advantage is the very tight integration of the graphics functions with the rest of the programs.
My company does so much graphing of output that we developed, with a fair amount of effort, our own Quickwin library to handle xy graphs with a minimal amount of additional effort.
Unfortunately Quickwin projects are MDI only, and they do not handle vector formats at all.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
What does not work creating the bitmap or doing the bitBlt in the paint loop?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Let me answer both points above. I cannot use Quickwin because my application is being driven by a modeless dialog. For the second, I guess it's the bitblt that is not working.
Brooks
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I no longer use Quickwin but I used to use it a lot and you can have modeless dialogs. I recall then documentation was a bit misleading on this subject. Have you verified that the bitmap structure that you are pointing at is valid?
I have not quite worked out what you are trying to do. is it capture a window data as a bmp, and repaint it adding some more graphic elements on top?
Did you look at http://msdn.microsoft.com/en-us/library/windows/desktop/dd183402(v=vs.85).aspx
I have my own working fortrainised version of that if it helps....
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You were right about the beginpaint/endpaint in that is does something you don't see and it is apparently necessary.
To answer your question, I have a set of radiobuttons in a modeless dialog and when the user clicks on one of the radiobuttons, I want to bitblt a bitmap onto the screen so I don't have to redraw it all the time and I want it done quickly. The types of graphs are (1) a text only, (2) a complex graph, (3) another comples graph mixed with some text, (4) a histogram of some pseudo-random sample, and (5) is another text window. All of these bitmaps are done when certain buttons and data are fed to the dialog and do not occur during a WM_PAINT event.
Thanks,
Brooks V
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Andrew,
Yes I would like to see the capture routine.
Thanks,
Brooks V
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
module capture_image
use :: ifwin, only: handle, t_rect, bool, sint, LPVOID, t_bitmap, t_BITMAPFILEHEADER, t_BITMAPINFOHEADER, &
DWORD, SIZE_T, T_POINT, NULL, GetDC, CreateCompatibleDC, GetClientRect, GetWindowRect, &
CreateCompatibleBitmap, SelectObject, BitBlt, ScreenToClient, SRCCOPY, GetObject, BI_RGB, &
GHND, GlobalAlloc, GlobalLock, GetDIBits, DIB_RGB_COLORS, GENERIC_WRITE, CREATE_ALWAYS, &
FILE_ATTRIBUTE_NORMAL, CreateFile, WriteFile, GlobalUnlock, GlobalFree, CloseHandle, &
DeleteObject, ReleaseDC, INVALID_HANDLE_VALUE
use, intrinsic :: ISO_C_BINDING, only: C_SIZEOF, C_INTPTR_T, C_LOC
!!!!!use axs6, only: cc_getlasterror !
implicit none
private
public :: CaptureAnImageToBMP_file , Write_pixarrayToBMP_File
contains
subroutine cc_getlasterror() ! dummy error handler provide your own
end subroutine cc_getlasterror
subroutine CaptureAnImageToBMP_file(hWnd,gfile,iopt,istat)
!based on parts of C++ example at http://msdn.microsoft.com/en-us/library/windows/desktop/dd183402(v=vs.85).aspx
!MSDN Topic "Capturing an Image" // GDI_CapturingAnImage.cpp : Defines the entry point for the application.
implicit none
integer(handle),intent(in) :: hWnd ! handle to window to capture
character(len=*),intent(in) :: gfile ! name of BMP file to write, must be c string
integer, intent(in) :: iopt ! 0 to capture whole window, 1 for just client area of window
integer, intent(out) :: istat ! error status 0=OK, <0 NOK
integer(handle) :: hdcWindow ! hDc
integer(handle) :: hdcMemDC ! hDc
type(t_rect) :: rcClient ! client coord bit grab rectangle of hWnd
integer(bool) :: bret
integer(sint) :: isint, isize
integer(handle) :: hbmWindow ! HBITMAP
integer(LPVOID) :: ilpvoid ! HGDIOBJ
type(t_bitmap) :: bmpWindow
type(t_BITMAPFILEHEADER) :: bmfHeader
type(t_BITMAPINFOHEADER) :: bi
integer(SIZE_T) :: dwBmpSize ! another 4 or 8 byter like handle
integer(HANDLE) :: hDIB
integer(LPVOID) :: ilpbitmap
integer(HANDLE) :: ihan ! HGLOBAL
integer(HANDLE) :: hfile
integer(DWORD) :: dwBytesWritten, dwSizeofDIB
type(T_POINT) :: tp1, tp2
integer(C_INTPTR_T) :: locvar, locbi ! integer pointers to data for api calls
istat=NULL !assume OK
hdcMemDC=NULL ; hbmWindow=NULL !init handles
hdcWindow = GetDC(hWnd) !Retrieve the handle to a display device context for the window.
! Create a compatible DC which is used in a BitBlt from the window DC
hdcMemDC = CreateCompatibleDC(hdcWindow)
if(hdcMemDC == NULL) then !"CreateCompatibleDC has failed"
istat=-1; goto 999
endif
if(iopt == 1) then
bret=GetClientRect(hWnd, rcClient) ! Get the client area for size calculation top rt (0,0)
else
bret=GetWindowRect(hWnd, rcClient) ! use the whole window area, this is in screen coords
tp1%x=rcClient%left; tp1%y=rcClient%top
tp2%x=rcClient%right; tp2%y=rcClient%bottom
bret=ScreenToClient(hwnd,tp1) ! convert to client area
bret=ScreenToClient(hwnd,tp2) ! convert to client area
rcClient%left = tp1%x ; rcClient%top = tp1%y
rcClient%right = tp2%x ; rcClient%bottom = tp2%y !that conversion is tedious!!!
endif
! Create a compatible bitmap from the Window DC
hbmWindow = CreateCompatibleBitmap(hdcWindow, rcClient%right-rcClient%left, rcClient%bottom-rcClient%top)
if(hbmWindow == NULL) then !"CreateCompatibleBitmap Failed"
istat=-2; goto 999
endif
ilpvoid=SelectObject(hdcMemDC,hbmWindow) ! Select the compatible bitmap into the compatible memory DC.
! Bit block transfer into our compatible memory DC
bret = BitBlt(hdcMemDC, & ! target dc for bit copy
0_sint, & ! target left
0_sint, & ! target top
rcClient%right-rcClient%left, & ! width
rcClient%bottom-rcClient%top, & ! height
hdcWindow, & ! source hdc
rcClient%left, & ! source left (client coord)
rcClient%top, & ! source right(client coord)
SRCCOPY) ! just copy don't merge /dither etc
if(bret == NULL) then !"BitBlt has failed"
istat=-3
goto 999
endif
isize = int(c_sizeof(bmpWindow),sint) !note c_sizeof is 4 or 8 byte dependent on platform
isint = GetObject(hbmWindow,isize,transfer(c_loc(bmpWindow),locvar)) ! Get the BITMAP from the HBITMAP
! fill the bitmapinfoheader
bi%biSize = int(c_sizeof(bi),dword)
bi%biWidth = bmpWindow%bmWidth
bi%biHeight = bmpWindow%bmHeight
bi%biPlanes = 1
bi%biBitCount = 32
bi%biCompression = BI_RGB
bi%biSizeImage = NULL
bi%biXPelsPerMeter = NULL
bi%biYPelsPerMeter = NULL
bi%biClrUsed = NULL
bi%biClrImportant = NULL
dwBmpSize = ((bmpWindow%bmWidth * bi%biBitCount + 31) / 32) * 4 * bmpWindow%bmHeight ! size of the bitmap
hDIB = GlobalAlloc(GHND,dwBmpSize) !make a buffer
if( hdib == NULL) call cc_getlasterror()
ilpbitmap = GlobalLock(hDIB) !protect buffer and get a handle to it
if( ilpbitmap == NULL) call cc_getlasterror()
! Gets the "bits" from the bitmap and copies them into a buffer which is pointed to by ilpbitmap
locbi= transfer(c_loc(bi),locvar) !memory address of var in integer(C_INTPTR_T) form
isint = GetDIBits(hdcWindow, hbmWindow, 0,bmpWindow%bmHeight, ilpbitmap,locbi, DIB_RGB_COLORS)
! A file is created, this is where we will save the screen capture.
hFile = CreateFile(gfile//char(0), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)
if( hfile == INVALID_HANDLE_VALUE) then
call cc_getlasterror()
istat=-4
goto 999
endif
! Add the size of the headers to the size of the bitmap to get the total file size
dwSizeofDIB = dwBmpSize + c_sizeof(bmfHeader) + c_sizeof(bi)
bmfHeader%bfType = int(z'4D42') ! "BM" bfType must always be BM for Bitmaps
bmfHeader%bfSize = dwSizeofDIB ! Size of the file SOF
bmfHeader%bfReserved1 = NULL ! where SOF is 8 bytes, could overflow here and still conform BTW
bmfHeader%bfReserved2 = NULL ! the reserved bytes define the application that made - redundant
bmfHeader%bfOffBits = c_sizeof(bmfHeader) + c_sizeof(bi) ! Offset to where the actual bitmap bits start.
dwBytesWritten = NULL
locvar=transfer(c_loc(dwBytesWritten),locvar) !memory address of var in integer(C_INTPTR_T) form
bret = WriteFile(hFile, transfer(c_loc(bmfHeader),locvar), int(c_sizeof(bmfHeader),Sint), locvar, NULL)
bret = WriteFile(hFile, locbi, int(c_sizeof(bi),Sint), locvar, NULL)
bret = WriteFile(hFile, ilpbitmap, int(dwBmpSize,sint), locvar, NULL)
bret = GlobalUnlock(hDIB) ! Unlock and Free the DIB from the heap
if(bret == NULL) call cc_getlasterror()
ihan = GlobalFree(hDIB)
bret = CloseHandle(hFile) ! Close the handle for the file that was created
999 continue !cleanup
bret = DeleteObject(hbmWindow)
bret = DeleteObject(hdcMemDC)
isint = ReleaseDC(hWnd,hdcWindow)
end subroutine CaptureAnImageToBMP_file
subroutine Write_pixarrayToBMP_File(bmpixels,bmWidth,bmHeight, gfile, istat)
integer(DWORD), intent(in) :: bmpixels(*)
integer(DWORD), intent(in) :: bmWidth, bmHeight
character(len=*),intent(in) :: gfile ! name of BMP file to write, must be c string
integer, intent(out) :: istat ! error status 0=OK, <0 NOK
integer(bool) :: bret
!type(t_bitmap) :: bmpWindow
type(t_BITMAPFILEHEADER) :: bmfHeader
type(t_BITMAPINFOHEADER) :: bi
integer(SIZE_T) :: dwBmpSize ! another 4 or 8 byter like handle
integer(HANDLE) :: hfile
integer(DWORD) :: dwBytesWritten, dwSizeofDIB
integer(C_INTPTR_T) :: LocVar, LocBitmap, LocBmfHeader, LocBi ! integer pointers to data for api calls
istat = 0
! fill the bitmapinfoheader
bi%biSize = int(c_sizeof(bi),dword)
bi%biWidth = bmWidth
bi%biHeight = bmHeight
bi%biPlanes = 1
bi%biBitCount = 32
bi%biCompression = BI_RGB
bi%biSizeImage = NULL
bi%biXPelsPerMeter = NULL
bi%biYPelsPerMeter = NULL
bi%biClrUsed = NULL
bi%biClrImportant = NULL !end subroutine Write_pixarrayToBMP_File
dwBmpSize = (( bmWidth * bi%biBitCount + 31) / 32) * 4 * bmHeight ! size of the bitmap
! Add the size of the headers to the size of the bitmap to get the total file size
dwSizeofDIB = dwBmpSize + c_sizeof(bmfHeader) + c_sizeof(bi)
bmfHeader%bfType = int(z'4D42') ! "BM" bfType must always be BM for Bitmaps
bmfHeader%bfSize = dwSizeofDIB ! Size of the file SOF
bmfHeader%bfReserved1 = NULL ! where SOF is 8 bytes, could overflow here and still conform BTW
bmfHeader%bfReserved2 = NULL ! the reserved bytes define the application that made - redundant
bmfHeader%bfOffBits = c_sizeof(bmfHeader) + c_sizeof(bi) ! Offset to where the actual bitmap bits start.
dwBytesWritten = NULL
LocVar = transfer(c_loc(dwBytesWritten),LocVar) ! memory address of var in integer(C_INTPTR_T) form
LocBitmap = transfer(c_loc(bmpixels), LocVar) ! memory address of bitmap start
LocBmfHeader = transfer(c_loc(bmfHeader), LocVar)
LocBi = transfer(c_loc(bi), LocVar)
hFile = CreateFile(gfile//char(0), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)
if( hfile == INVALID_HANDLE_VALUE) then
call cc_getlasterror()
istat=-4
goto 999
endif
bret = WriteFile(hFile, LocBmfHeader, int(c_sizeof(bmfHeader),Sint), locvar, NULL)
bret = WriteFile(hFile, LocBi, int(c_sizeof(bi),Sint), locvar, NULL)
bret = WriteFile(hFile, LocBitmap, int(dwBmpSize,Sint), locvar, NULL)
999 continue
bret = CloseHandle(hFile) ! Close the handle for the file that was created
end subroutine Write_pixarrayToBMP_File
end module capture_image
That code works the MSDN ref is in the code the error handler is a dummy routine. The write pixarray I use when I grab OPENGL screen buffers.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This may be closed out. Thanks, Brooks V
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
dboggs wrote:
Since you want bitmap graphs, you might also consider a Quickwin project. This gives you access to powerful primitive graphics functions, similar (but different) from the Windows functions you showed. The advantage over SciGraph or other 3rd party libraries is that you have complete control over every detail of your graph. The disadvantage is that you have to take control over every detail of your graph. Another advantage is the very tight integration of the graphics functions with the rest of the programs.
My company does so much graphing of output that we developed, with a fair amount of effort, our own Quickwin library to handle xy graphs with a minimal amount of additional effort.
Unfortunately Quickwin projects are MDI only, and they do not handle vector formats at all.
[/quote
I have used PGPlot in Quickwin projects quite a bit. It makes clean 2D graphs and is easy to use. An added bonus is that you can make it output Postscript files (from your QuickWin program), so if you need real publication-quality graphs that look the same as the graphs on the screen you can get these easily too.
http://www.astro.caltech.edu/~tjp/pgplot/
https://sukhbinder.wordpress.com/2012/01/04/how-to-use-pgplot-in-windows-with-intel-fortran/
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page