Getting the Width of a Window

Hi,

I need the width of a window. I try to do this as follows:

1
2
3
LPRECT tarWnd = 0;
GetClientRect(hWnd,tarWnd);
int width = tarWnd->right - tarWnd->left;


However for some reason whenever the tarWnd LPRECT is accessed the program acts as if the break; statement were used skipping the code after it. Am I doing something wrong or is this not the way to get the windows width? I think it could be because the GetClientRect() function fails but I don't know why it would do.
I'd like to add my window handle is definitely valid as seemingly all other function calls using it work.

EDIT: The code I am using is slightly different.

1
2
3
4
5
6
7
8
9
RECT* tileClientArea = 0;
GetClientRect(tile, tileClientArea);
if (tileClientArea == NULL)
	MessageBox(hWnd, L"Error", L"Error", 1);
else
	int width = tileClientArea->right - tileClientArea->left;

DWORD tmp = GetLastError();
palette->DrawTiles(hdc, 0);


Message box pops up saying "Error" meaning that the RECT* is NULL however GetLastError() returns 0 meaning the operation completed successfully.
Last edited on
Use GetWindowRect. Subtract the right from the left to get the width and the bottom from the top to get the height.
1
2
3
4
5
6
RECT rect;
if(GetWindowRect(hwnd, &rect))
{
  int width = rect.right - rect.left;
  int height = rect.bottom - rect.top;
}


Your code is wrong because LPRECT or RECT* is just a pointer, you don't allocate memory for RECT structure anywhere.
Last edited on
For future reference?

When it comes to the Win32 API, all calls which use a pointer parameter to receive a value assume that the caller has pointed at enough accessible memory to hold the value.

As the help for GetWindowRect. says:

A pointer to a RECT structure that receives the screen coordinates of the upper-left and lower-right corners of the window.

http://msdn.microsoft.com/en-us/library/windows/desktop/ms633519%28v=vs.85%29.aspx

That is, you have a RECT which you point it at! (Your RECT can be on the stack or heap, but it's got to be there.)

In those cases where memory will be allocated for you, the parameter will be a pointer to a pointer. You have to provide the storage for just the pointer; the callee will set it to point at the space they allocate.)

(Or the pointer will be the return value of the function...)

Andy

PS There are a few more advanced Win32 API calls which have parameters which point at a header structure, rather than a complete scructure. These calls required you to allocate enough storage that the buffer can receive a range of data. You then use the information in the header to find out what has actually been obtained and then use a cast to obtain a pointer to the correct structure type. Just in case...
Last edited on
Thanks for the info, i read the documentation, i was just unclear of what went on in the function, i thought it created a copy and assigned its address to the pointer you gave. I am just getting into win32 programming.
If you think about a bit more...

The signature of GetClientRect is:

BOOL GetClientRect(HWND hWnd, LPRECT lpRect);

Where HWND is a window handle, and LPRECT a (long) pointer to a RECT.

(the long means nothing these days, but in Win16 times there were near and far pointers: LPSTR was equivalent to char far *, whereas now it's just char*)

Far pointer
http://en.wikipedia.org/wiki/Far_pointer

The thing to notice is that both parameters are passed by value, so GetClientRect gets a copy of your pointer.

If GetClientRect was stupid enough to try and change the value, you wouldn't notice: the value of your pointer would be the same as before you made the call, which is of no use. You'd never see what they pointed at, and there would be a memory leak as you couldn't free the allocated memory it allocated later on.

If the function did allocate memory for you, it would get you to pass it the address of your variable. That way they can change your variable for you and everything works: you get the new value and can free the memory later.

1
2
3
4
5
6
7
8
9
LPRECT pRect = NULL;
BOOL GetClientRectWithNew(hWnd, &pRect);

// GetClientRectWithNew deferences your pointer and set it to point
// at the memory they allocated: *ppRect = <some memory>

// You use pRect...

delete pRect;


In C++ you could use a reference to a pointer for the second parameter, but most of the Win32 API is C, which doesn't know what a reference it.

Now the reason this approach is not used in general by the Win32 API is that the module calling new (which would be User32.dll, if this was what it did) and the module calling delete must be using the same C++ runtime. This isn't always the case, especially if components are upgraded separately (they can start off in step, but end up using different runtimes.

In the case where they do allocate memory for you, they also provide a function to free the memory. This allows the same DLL that allocated the memory to free it. But the approach that GetClientRect uses is safer for routine use as there's less chance of forgetting to free memory.

So, when you write a C style DLL function, you should avoid passing memory out of functions. If you do, you need to provide a corresponding free.

And for the same reason, C++ function which return things like std::strings and std::vectors can be a real problem when it comes to DLL versioning, C++ linkage and DLLs should be avoided as a rule (that is, unless the modules will always be updated together).
Last edited on
Topic archived. No new replies allowed.