Saturday, February 20, 2010

To check the visibility status of a window(or control)in Wiin32/VC++

1.

if(WS_VISIBLE&(GetWindowLongPtr(GetDlgItem(hwndDialog,IDC_EDIT1),GWL_STYLE)) )
{
//Control is visible
}

2.

if( TRUE == IsWindowVisible(GetDlgItem(hDialog, IDC_EDIT1))){
{
//Control is visible
}

Memory Values and their Meanings [Windows Memory Debug Codes]

When we declare variables without initializing them, windows memory management functions initialize memory with some special values, depending on their type (static or dynamic). The compiler assigns some default values to different types of variables. These values become very useful during debugging because we can find why some exceptions has occurred. Some common values and their meanings are discussed below:

Windows NT memory codes

* 0xfeeefeee - Memory reserved to heap allocation but has not been allocated yet [ OS fill heap memory, which was marked for usage, but wasn't allocated by HeapAlloc() or LocalAlloc(). Or that memory just has been freed by HeapFree(). ]

* 0xABABABAB - Memory following a block allocated by LocalAlloc().

* 0xBAADF00D - "Bad Food". This is memory allocated via LocalAlloc( LMEM_FIXED, ... ). It is memory that has been allocated but not yet written to.

Compiler initializations

* 0xcccccccc - Uninitialized stack variable [ 0xCC, 0xCCCCCCCC - The /GX Microsoft Visual C++ compiler option initializes all local variables which are not explicitly initialized by the program. All memory used by these variables are thus filled with 0xCC, 0xCCCCCCCC. ]

Debug codes provided by C runtime library

* 0xcdcdcdcd - Uninitialized heap variables( i.e. New objects) [ New objects are filled with 0xCD when they are allocated.]
* 0xfdfdfdfd - Padding around an array(called 'No-man's land memory'. They are Extra bytes that belong to the internal block allocated, but not the block you requested. They are placed before and after requested blocks and are used for data bound checking.)
* 0xdddddddd - Released heap variable (delete or free)[ Freed blocks. The freed blocks kept unused in the debug heap's linked list when the _CRTDBG_DELAY_FREE_MEM_DF flag is set are currently filled with 0xDD. In some cases it will be overwritten by some other debug functions

When a debugger is attached to a process, HeapAlloc will initialize memory to 0xbaadf00d and HeapFree will set deleted memory to 0xfeeefeee.

So that’s where HINSTANCES come from

I realize that this is probably totally trivial for real Win32 developers, but it took me long enough to find this that I’ll blog it and help Google guide future developers.

RegisterClassEx requires an HINSTANCE…I always thought of this as “that thing that is passed to WinMain. Now I realize - it’s a reference to the DLL that the Window Class function is in

So if you’re like me and want to register a class from library code without having that HINSTANCE from WinMain and you’re not using DLLs, you can just use GetModuleHandle(NULL) and call it a day. Easy!

Decoding Windows Network messages

We can decode error codes easily by using the command prompt by Just typing

net helpmsg error code

Note : The (error code)message no. should be in decimal

Setting focus to controls in a dialog box using WM_NEXTDLGCTL

We usually use SetFocus function to set the focus to a control. But in a dialog box, this may cause some small issues like sometimes the focus rectangle may be on one button while another button is highlighted, or sometimes having no default button at all. So we need to use another method for that.

If we use SetFocus function, the highlighting behavior may not be consistent. The highlight may depend on many factors like the previous input etc.
This behavior is because of the concept of "default button". The default button is typically drawn with a distinctive look, and will be the button that gets pushed when we hit Enter.

We can get the default button handle by sending the DM_GETDEFID message; similarly, we can change the default button by sending the DM_SETDEFID message. The default button can be set in the resource file itself, by setting the property “ Default Button”.

When the dialog box moves focus to a pushbutton, that pushbutton becomes the new default button. But when the dialog box moves focus to some other controls, the old default button will again be the default button. The dialog manager remembers which control was the default button when the dialog was initially created, and when it moves focus to something that isn't a button, it restores that original button as the default button.

The SetFocus function is a window manager function. If we use this, we are going directly to the window manager, bypassing the dialog manager. This can cause some issues like having focus rectangle on a button and the highlighting on another.
To avoid this problem, don't use SetFocus to change focus on a dialog. Instead, use the WM_NEXTDLGCTL message.

SendMessage(hdlg, WM_NEXTDLGCTL, (WPARAM)hwndControl, TRUE);

The DefDlgProc function handles the WM_NEXTDLGCTL message by updating the internal dialog manager bookkeeping, deciding which button should be default, etc.
Using SetFocus we can move the Focus rectangle to a dialog control. But for push buttons, the blue highlight seen on them can’t be moved to another Pushbutton using SetFocus. So better use this message to set the focus in a dialog – always.

List View ToolTip issue in Windows XP

In Windows XP, if the List View item text [item name] is long, the tooltip may not show all the characters, and may be truncated. In Vista and 2000, it is managed by the OS itself.

Fix:

Just before the tooltip is displayed, the List View will give LVN_GETINFOTIP notification. In the handler for that, we can get the Tooltip info. Structure by

LPNMLVGETINFOTIP pGetInfoTip = (LPNMLVGETINFOTIP) lParam;
if( wcslen ( pGetInfoTip->pszText )) {

//do the string processing on pGetInfoTip->pszText

Set the value of pGetInfoTip->pszText.

StringCbCopyW( pGetInfoTip->pszText, (wcslen( pwzTmp ) + 1) * sizeof(WCHAR) , pwzTmp)); //Setting the tooltip text

// LVN_GETINFOTIP notification will be obtained only if we set the Listview extended style

DWORD ex_style = ListView_GetExtendedListViewStyle(hwndLView);
ex_style |= LVS_EX_LABELTIP | LVS_EX_INFOTIP;
ListView_SetExtendedListViewStyle(hwndLView , ex_style);

//String Processing

HGDIOBJ hFont = reinterpret_cast(SendMessage( hwndListView, (UINT) WM_GETFONT, (WPARAM) 0, (LPARAM)0 ) );

HGDIOBJ hOldFont = SelectObject( hLViewDC , hFont );

GetTextExtentPoint32( hLViewDC , (LPCTSTR)pwzTmp, nLineWidth , &sSize );
if( sSize.cx >= ( nWidth ) ){
pwzDestnText[nDestnIndex] = L'\n';
nDestnIndex++;
. . .

[The Tooltip text is extracted, manipulated and set back to the tooltip structure.]

Customizing Win32 Scrollbar

To make the scrollbar thumb size proportional to the amount of data displayed, we need to set the page size of the scroll bar. If we don’t set the page size for the scroll bar explicitly, the thumb size will be the default size given by windows. This is not proportional to the amount of data displayed on the screen. So we need to set the page size to the scroll bar explicitly.


The page size of the scroll bar can be set using SetScrollInfo function, with the required value of page filled in the corresponding field in a SCROLLINFO structure.

The range of the scroll bar should be (the total size of data displayed -1), and the page size should be the amount of data displayed at a time.

Also, the condition for stopping the scroll is taken from the formulae
MaxScrollPos = MaxRangeValue - (PageSize - 1)

i.e. The maximum scroll position of the scrollbar is dependant on the Range and the page size as said in the above formula. A check based on this can be added in the procedure for scrolling the base area dialog. Otherwise the scrolling may not stop even when all the data has been scrolled up.

Though many developer sites and books said the scroll bar range should be set to (Max height of data -1), I was trying to get why so. And the result? follows :

Total area to be displayed = MaxHt
Total area displayed at a time = PageSize
Area to be scrolled = MaxHt - PageSize

Let's take No. of ScrollBar positions = nPos.
nPos = MaxHt - PageSize ---- (1)

We have nPos = Range - ( PageSize -1 ) ----- (2) [ MSDN ]
= Range - PageSize +1
= Range +1 - PageSize

i.e. nPos = ( Range+1) - PageSize. -------- (3)

From (1) and (3), nPos = MaxHt - PageSize = (Range +1) - PageSize

=> MaxHt = Range +1
=> Range = MaxHt -1