- 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