Redrawing Contents of Window

I am still learning to program Native Windows and the GDI. I am wanting to make a simple picture viewer. Here is what I have. These two cases are in seperate switch statements. I didn't want to post the whole program for obvious reasons.

HBITMAP bitMap = NULL;
char fileName[MAX_PATH] = "";

case OPEN_MENU:
{
OPENFILENAME ofn;
MessageBox(hWnd, fileName, "Test", MB_OK);
ZeroMemory(&ofn, sizeof(ofn));

ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hWnd;
ofn.lpstrFilter = "BMP (*.bmp)\0*.bmp\0";
ofn.lpstrFile = fileName;
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
ofn.lpstrDefExt = "bmp";

if(GetOpenFileName(&ofn))
{
//fileName = (LPCSTR)fileName;
MessageBox(hWnd, fileName, "Test", MB_OK);
bitMa[ = LoadBitmap(GetModuleHandle(NULL), (LPCSTR)fileName);
InvalidateRect(hWnd, NULL, TRUE);
UpdateWindow(hWnd);
//PostMessage(hWnd, WM_PAINT, 0, 0);
}
}
break;

case WM_PAINT:
{
/*if(fileName != "")
{
MessageBox(hWnd, fileName, "Test", MB_OK);
}*/
BITMAP bp;
PAINTSTRUCT ps;

HDC hdc = BeginPaint(hWnd, &ps);

HDC hdcmem = CreateCompatibleDC(hdc);
HBITMAP old = (HBITMAP)SelectObject(hdcmem, cyberwolf);

GetObject(bitMap, sizeof(bp), &bp);

BitBlt(hdc, 0, 0, bp.bmWidth, bp.bmHeight, hdcmem, 0, 0, SRCCOPY);

SelectObject(hdcmem, old);
DeleteObject(hdcmem);

EndPaint(hWnd, &ps);
}
break;

When I run it with this, a Open Dialog opens. I select the image I want to open, but it won't display it. I have checked everything. I don't know what is wrong. Does anyone know? Thanks.
Last edited on
After
EndPaint()
Just add
 
Invalidate();

Rajendra.
@ gamewolfwhat is cyberwolf that you are selecting into the memory device context in the WM_PAINT message???

@ rajenipcv should you call theinvalidate function while you are in the middle of handling a WM_PAINT message?
@ guestgulkan
Yes.
O cyberwolf shouldn't be there

Whe I use Invalidate();, it says 'Invalidate: Identifier not found'.
@ rajenipcv should you call the invalidate function while you are in the middle of handling a WM_PAINT message?
@ guestgulkan
Yes.
No.

The WM_PAINT message is sent in response to one or more calls to the invalidation functions. If you immediately invalidate what you just drew, you'll only put your application into a time-consuming cycle of constant repainting.

I don't actually see anything wrong with your painting. At the end of the OPEN_FILE case you properly call InvalidateRect() and even UpdateWindow() (though the second isn't strictly necessary --but don't take it out ;-)

The problem comes from the use of LoadBitmap(). That function only loads resources linked into the executable. It won't load files. :-O Yep. Only linked resources. Hence, the resource fails to load and any attempt to draw NULL in WM_PAINT fails.

Probably the simplest fix is to use the LoadImage() function. However, it doesn't work on Windows NT, so I'll recommend you take the effort to load it properly. (It also has a bug or two involving transparent colors.) You would think that the Win32 API would provide a function to do this for us...

Basically you have to extract and assemble the bitmap yourself. Unfortunately there isn't a whole lot of straight-forward information about this on the internet, so here's a little function to do it for you.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <windows.h>

HBITMAP BMPLoadFromFile( LPCTSTR filename )
  {
  HANDLE           f;
  BITMAPFILEHEADER bmFH;
  DWORD            size;
  HGLOBAL          g;
  LPVOID           p;
  HDC              dc;
  DWORD            count;
  BOOL             ok;
  HBITMAP          result = 0;

  /* Open the bitmap file */
  f = CreateFile(
        filename,
        GENERIC_READ,
        FILE_SHARE_READ,
        NULL,       /* no security attributes: handle cannot be inherited */
        OPEN_EXISTING,
        FILE_FLAG_SEQUENTIAL_SCAN, /* optimize for how we'll use the file */
        NULL
        );
  if (f == INVALID_HANDLE_VALUE) return 0;

  /* Read and validate the bitmap file header */
  ok = ReadFile( f, (LPVOID)&bmFH, sizeof( BITMAPFILEHEADER ), &count, NULL );
  if (!ok || (count != sizeof( BITMAPFILEHEADER )) || (bmFH.bfType != 0x4D42))
    goto done_file;

  /* Get the size of the bitmap structure */
  size = GetFileSize( f, NULL );
  if (size == 0xFFFFFFFF) goto done_file;
  size -= sizeof( BITMAPFILEHEADER );

  /* And try to allocate and load it */
  g = GlobalAlloc( GHND, size );
  if (g == NULL) goto done_file;

  p = GlobalLock( g );
  if (p == NULL) goto done_global;

  ok = ReadFile( f, p, size, &count, NULL );
  if (!ok || (count != size)) goto done_global;

  /* OK, now we can get down to business and turn our data into an HBITMAP */
  dc = GetDC( NULL );
  if (dc == NULL) goto done_global;

  result = CreateDIBitmap(
             dc,
             (BITMAPINFOHEADER*)p,
             CBM_INIT,
             (LPVOID)((CHAR*)p +bmFH.bfOffBits),  /* don't assume packed .bmp */
             (BITMAPINFO*)p,
             DIB_RGB_COLORS
             );

  ReleaseDC( NULL, dc );

  done_global: GlobalFree( g );
  done_file:   CloseHandle( f );

  return result;
  }

If it fails to load you'll get back NULL. Otherwise be sure to dispose of the HBITMAP you get from this using DeleteObject(). And of course you are linking with libgdi32, right?

Hope this helps.
Last edited on
> Probably the simplest fix is to use the LoadImage() function. However, it doesn't work on Windows NT,

What is this Bullshit ?
First off, you had better fix your language.

Secondly, I have the good sense to review the Win32 SDK documentation when posting stuff.
http://www.piclist.com/techref/os/win/api/win32/func/src/f53_13.htm
Quote:
Windows NT: LR_LOADFROMFILE is not supported.

Thirdly, if you want to take issue with something, don't just whine and complain. Either suggest something better and correct or link to something that does.

It appears that the latest MSDN LoadImage documentation has removed the caveat about LR_LOADFROMFILE (see http://msdn.microsoft.com/en-us/library/ms648045.aspx ) and a quick check with Google advised me that some people report that NT versions as old as 3.51 work just fine with it. Given the MSDN info, I suspect that Microsoft may have fixed it with a service pack.

If you want more information about handling BMP files beyond what I have posted, this is a very good tutorial:
http://www.runicsoft.com/bmp.php

PS. There is a little blue "edit" button on the bottom right of your post. Please use it.
> Probably the simplest fix is to use the LoadImage() function. However, it doesn't work on Windows NT,

What is this Bullshit ?


Sadly, Thats a typical unhelpful response I would expect from him Duoas. It's entirely feasible someone is doing work on WindowsNT at a university or polytechnic somewhere. Or even an in organisation (banks are shockers for old OS's).
Hence, the reason I recommend against using that function. ;-)
Last edited on
MSDN is the only available doc
http://msdn.microsoft.com/en-us/library/ms648045.aspx
It has always worked on NT >= 3.51, for 13 years...
(and I've used it at least 2000 times on every MS OS, it has always worked perfectly)
Last edited on
MSDN is the only available doc
That's funny because I have a fairly extensive collection of Microsoft's own help files on my harddisk. The danger with MSDN is that Microsoft is notorious for modifying their documentation to represent the current state of things without any respect for past states.

It has always worked on NT >= 3.51, for 13 years...
If some past employee on the Redmond documentation team felt it noteworthy to indicate that LoadImage() cannot do LR_LOADFROMFILE on Windows NT, then it is better to code against the possibility that someone, somewhere may have an ancient, unpatched, dysfunctional version of NT where LoadImage() will fail to load a BMP from file --no matter how many instances can be found where it works without problem. Anectdotal evidence is not proof of anything.

I have not personally experienced any problems with LoadImage( ... LR_LOADFROMFILE ) either. But then again, I have never used NT. If the OP can guarantee that his target audience is using 4.7x or greater then there isn't any problem. But if he can't, then he should code appropriately. That's all.
Topic archived. No new replies allowed.