child of tab dialog control cover the tab itself - c++

I create a tab control in WM_INITDIALOG this way:
INITCOMMONCONTROLSEX icex = {0};
icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
icex.dwICC = ICC_TAB_CLASSES;
InitCommonControlsEx(&icex);
TCITEM tie;
LPSTR text = "my tab";
tie.mask = TCIF_TEXT|TCIF_IMAGE;
tie.iImage = -1;
tie.pszText = text;
hTab = CreateWindow(WC_TABCONTROL, "", WS_CHILD |WS_CLIPSIBLINGS| WS_VISIBLE,
0,0, 400, 350, hWnd,NULL, g_hInstance, NULL);
TabCtrl_InsertItem(hTab,0,&tie);
TabCtrl_InsertItem(hTab,1,&tie);
TabCtrl_InsertItem(hTab,2,&tie);
and also I create two dialog here to show in each tab as content of the tab. I create them with toolbox selecting formview dialog:
hwndTabcontentDialog1 = CreateDialogParam( GetModuleHandle( NULL ),
MAKEINTRESOURCE( IDD_FORMVIEW1 ), hTab, (DLGPROC)Proc1,lParam );
hwndTabcontentDialog2 = CreateDialogParam( GetModuleHandle( NULL ),
MAKEINTRESOURCE( IDD_FORMVIEW ), hTab, (DLGPROC)Proc2,lParam );
now in WM_NOTIFY I am doing this to content of each tab when its clicked:
case WM_NOTIFY:
switch (((LPNMHDR)lParam)->code)
{
case TCN_SELCHANGE:
{
if( TabCtrl_GetCurSel( ( ( LPNMHDR ) lParam) -> hwndFrom ) == 0 ) {
ShowWindow( hwndTabcontentDialog1, SW_SHOW );
ShowWindow( hwndTabcontentDialog2, SW_HIDE );
} else {
ShowWindow( hwndTabcontentDialog1, SW_HIDE );
ShowWindow( hwndTabcontentDialog2, SW_SHOW );
}
}
now the tab is created and everything is fine(content of current tab is not visible), but when I click on one of the tab items the dialog cover all the tab control and you cant see the tabs anymore.
what is wrong ? what should I modify ?

Immediately after you create the dialogs reposition/resize them with MoveWindow. The TCM_ADJUSTRECT tab control message can help you figure out the proper position/size to make the dialogs.

Related

Dialog box freezes and stops responding

I have a very specific problem involving a modeless dialog box in my application.
The dialog box freezes and becomes unresponsive to any messages sent to it by other functions in my application. What is interesting is that my debugging tells me that it freezes when the dialog procedure has received just around 5000 messages that it DID NOT handle. The only explanation I can think of is that the Windows Message Queue may be full and it is more or less confirmed by the fact that the stream of messages going through the dialog box seem to tone down immensely.
Now - I've never used dialog boxes in conjunction with an ordinary main window before, and so I may be making illegal moves. By this I mean that I update the dialog box's controls (static texts and a list box) directly by sending the specific controls messages using SendMessage or SetWindowText functions.
What I think is weird is, that this technique works perfectly until 5000 messages have passed.
The main loop sends messages to the dialog box via the parent window handle and use of IsDialogMessage function.
Both the Main window and the dialog box still receives messages, but the dialog box freezes.
Is there a way for me to empty the message queue manually or check its current volume to check if that is actually the problem? I use PeekMessage function to retrieve my messages, which according to MSDN should remove a message from the bottom of the Message queue.
Here is how I've implemented My main loop ( I am pretty sure it's completely legal ):
while (true) //while there is a message
{
//if there was a windows message
if ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
if ( msg.message == WM_QUIT ) //if the message was WM_QUIT
return 0; //Exit the message loop
if ( !IsDialogMessage( m_StatusHwnd, &msg ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
else
{
advanceFrame();
}
}
I really hope one of you have an idea about what is wrong, because this is REALLY hard hard to debug!
The Dialog procedure is implemented like so: ( Sorry that you have to see my actual code )
First the static dialog procedure redirects the messages to a custom method:
BOOL CALLBACK DXCore::statusDlgProc( HWND hwnd,
UINT msg,
WPARAM wParam,
LPARAM lParam )
{
if ( msg == WM_INITDIALOG ) SetWindowLongPtr( hwnd, DWLP_USER, lParam);
DXCore * pCore = reinterpret_cast<DXCore*>( GetWindowLongPtr( hwnd, DWLP_USER ) ) ;
if ( pCore ) return pCore->displayStatusDlgProc( hwnd, msg, wParam, lParam );
//return the message for windows to handle it
return FALSE;
}
Then the actual procedure looks like this:
BOOL DXCore::displayStatusDlgProc( HWND hwnd,
UINT msg,
WPARAM wParam,
LPARAM lParam )
{
HBRUSH brush = CreateSolidBrush( COLORREF( RGB( 255, 0, 0 ) ) ); //red
HPEN blackPen = CreatePen( PS_SOLID, 2, COLORREF( RGB(0,0,0 ) ) );
HDC hdc; PAINTSTRUCT ps;
RECT clientArea;
GetClientRect( hwnd, &clientArea );
int gizmoRadius= 5;
m_GismoOrigon.x = clientArea.left + 150;
m_GismoOrigon.y = clientArea.top + 460;
//OutputDebugString( "Dillermand\n" );
dlgProcCounter += 1;
switch ( msg )
{
case WM_INITDIALOG:
m_FPSCount = GetDlgItem( hwnd, IDC_STATIC_FPS );
if ( !m_FPSCount ) MessageBox( NULL, "ghFPSCount", "DAMN", MB_OK );
m_CamPosX = GetDlgItem( hwnd, IDC_CAMPOSX );
if ( !m_CamPosX ) MessageBox( NULL, "ghCamPosX", "DAMN", MB_OK );
m_CamPosY = GetDlgItem( hwnd, IDC_CAMPOSY );
if ( !m_CamPosY ) MessageBox( NULL, "ghCamPosY", "DAMN", MB_OK );
m_CamPosZ = GetDlgItem( hwnd, IDC_CAMPOSZ );
if ( !m_CamPosZ ) MessageBox( NULL, "ghCamPosZ", "DAMN", MB_OK );
m_hStatusMessages = GetDlgItem( hwnd, IDSTATUS_PROGMSG );
if ( !m_hStatusMessages ) MessageBox( NULL, "ghStatusMessages", "DAMN", MB_OK );
else
{
SetParent( m_hStatusMessages, hwnd );
}
m_RunButton = GetDlgItem( hwnd, IDCSTATUS_RUN_BTN );
if ( !m_RunButton ) MessageBox( NULL, "ghRunButton ", "DAMN", MB_OK );
m_PauseButton = GetDlgItem( hwnd, IDSTATUS_PAUSE_BTN );
if ( !m_PauseButton ) MessageBox( NULL, "ghPauseButton", "DAMN", MB_OK );
SetWindowText( m_CamPosX, "0" );
SetWindowText( m_CamPosY, "0" );
SetWindowText( m_CamPosZ, "0" );
return TRUE;
case WM_PAINT:
hdc = BeginPaint( hwnd, &ps );
SelectObject( hdc, brush );
SelectObject( hdc, blackPen );
Ellipse( hdc, m_GismoOrigon.x - gizmoRadius, m_GismoOrigon.y - gizmoRadius, m_GismoOrigon.x + gizmoRadius, m_GismoOrigon.y + gizmoRadius ) ;
EndPaint( hwnd, &ps );
return TRUE;
case WM_COMMAND:
return TRUE;
case WM_NOTIFY:
return TRUE;
case WM_CTLCOLORSTATIC:
return TRUE;
case WM_TIMER:
return TRUE;
case WM_DESTROY:
if ( MessageBox( hwnd, "Exit Program?", "Do Not Want!", MB_YESNO ) == IDYES )
{
PostQuitMessage( 0 );
}
else ShowWindow(m_StatusHwnd, true );
return TRUE;
case WM_CLOSE:
DestroyWindow( m_StatusHwnd );
return TRUE;
default:
string s = std::to_string( dlgProcCounter ) + " Unhandled Dlg message: " + std::to_string( msg ) + "\n";
OutputDebugString( s.c_str( ) );
return (INT_PTR)FALSE;
}
return FALSE;
}
Your dialog procedure is creating two GDI objects, a brush and pen, every time it's called. It never destroys these objects. By default there's a 10,000 per process limit on GDI objects. Once you reach that limit the calls to create the objects will fail. Your code will then try to draw using invalid handle values, making it appear that your window has frozen.
The solution is to only create the objects once when handling the WM_INITDIALOG message. Also always check the return value of the functions you call for errors. If you had checked the return values to CreateSolidBrush and CreatePen you potentially could have figured this out earlier.

Win32: Add black borders to fullscreen window

I am trying to preserve content aspect ratio in fullscreen mode in Windows. I'd like to hide the rest of the desktop behind black borders if the display aspect ratio differs from the content aspect ratio. Is it possible to create fullscreen window with centered content and black borders with Win32 api?
In OS X this can be achieved quite easily with the following code:
CGSize ar;
ar.width = 800;
ar.height = 600;
[self.window setContentAspectRatio:ar];
[self.window center];
[self.window toggleFullScreen:nil];
If I run the above code in 16:9 display, my app goes to fullscreen mode, the content is centered (since it is 4:3) and I have black borders on both sides of the screen.
I have tried to implement the same functionality in Windows but I begin to wonder if it is even possible. My current fullscreen code maintains the aspect ratio and
centers the content, but shows the desktop on the both sides of the window if the fullscreenWidth and fullscreenHeight are not equal to displayWidth and displayHeight:
bool enterFullscreen(int fullscreenWidth, int fullscreenHeight)
{
DEVMODE fullscreenSettings;
bool isChangeSuccessful;
int displayWidth = GetDeviceCaps(m_hDC, HORZRES);
int displayHeight = GetDeviceCaps(m_hDC, VERTRES);
int colourBits = GetDeviceCaps(m_hDC, BITSPIXEL);
int refreshRate = GetDeviceCaps(m_hDC, VREFRESH);
EnumDisplaySettings(NULL, 0, &fullscreenSettings);
fullscreenSettings.dmPelsWidth = fullscreenWidth;
fullscreenSettings.dmPelsHeight = fullscreenHeight;
fullscreenSettings.dmBitsPerPel = colourBits;
fullscreenSettings.dmDisplayFrequency = refreshRate;
fullscreenSettings.dmFields = DM_PELSWIDTH |
DM_PELSHEIGHT |
DM_BITSPERPEL |
DM_DISPLAYFREQUENCY;
SetWindowLongPtr(m_hWnd, GWL_EXSTYLE, WS_EX_APPWINDOW | WS_EX_TOPMOST);
SetWindowLongPtr(m_hWnd, GWL_STYLE, WS_POPUP | WS_VISIBLE);
SetWindowPos(m_hWnd, HWND_TOPMOST, 0, 0, displayWidth, displayHeight, SWP_SHOWWINDOW);
isChangeSuccessful = ChangeDisplaySettings(&fullscreenSettings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL;
ShowWindow(m_hWnd, SW_MAXIMIZE);
RECT rcWindow;
GetWindowRect(m_hWnd, &rcWindow);
// calculate content position
POINT ptDiff;
ptDiff.x = ((rcWindow.right - rcWindow.left) - fullscreenWidth) / 2;
ptDiff.y = ((rcWindow.bottom - rcWindow.top) - fullscreenHeight) / 2;
AdjustWindowRectEx(&rcWindow, GetWindowLong(m_hWnd, GWL_STYLE), FALSE, GetWindowLong(m_hWnd, GWL_EXSTYLE));
SetWindowPos(m_hWnd, 0, ptDiff.x, ptDiff.y, displayWidth, displayHeight, NULL);
return isChangeSuccessful;
}
The easiest way to accomplish what you are looking for is to create a child window (C) to render your content, leaving any excess space to the parent (P).
P should be created using a black brush for its background. Specify (HBRUSH)GetStockObject(BLACK_BRUSH) for the hbrBackground member of the WNDCLASS structure when registering the window class (RegisterClass). To prevent flicker while erasing the background, P should have the WS_CLIPCHILDREN Window Style.
Whenever P changes its size, a WM_SIZE message is sent to P's window procedure. The handler can then adjust C's position and size to maintain the aspect ratio.
To create a borderless child window C, use the WS_CHILD | WS_VISIBLE window styles in the call to CreateWindow. If you want to handle mouse input in the parent P instead, add the WS_DISABLED window style.
Sample code (error checking elided for brevity):
#define STRICT 1
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
// Globals
HWND g_hWndContent = NULL;
// Forward declarations
LRESULT CALLBACK WndProcMain( HWND, UINT, WPARAM, LPARAM );
LRESULT CALLBACK WndProcContent( HWND, UINT, WPARAM, LPARAM );
int APIENTRY wWinMain( HINSTANCE hInstance,
HINSTANCE /*hPrevInstance*/,
LPWSTR /*lpCmdLine*/,
int nCmdShow ) {
Both main and content window classes need to be registered. The registration is almost identical, with the exception of the background brush. The content window uses a white brush so that it's visible without any additional code:
// Register main window class
const wchar_t classNameMain[] = L"MainWindow";
WNDCLASSEXW wcexMain = { sizeof( wcexMain ) };
wcexMain.style = CS_HREDRAW | CS_VREDRAW;
wcexMain.lpfnWndProc = WndProcMain;
wcexMain.hCursor = ::LoadCursorW( NULL, IDC_ARROW );
wcexMain.hbrBackground = (HBRUSH)::GetStockObject( BLACK_BRUSH );
wcexMain.lpszClassName = classNameMain;
::RegisterClassExW( &wcexMain );
// Register content window class
const wchar_t classNameContent[] = L"ContentWindow";
WNDCLASSEXW wcexContent = { sizeof( wcexContent ) };
wcexContent.style = CS_HREDRAW | CS_VREDRAW;
wcexContent.lpfnWndProc = WndProcContent;
wcexContent.hCursor = ::LoadCursorW( NULL, IDC_ARROW );
wcexContent.hbrBackground = (HBRUSH)::GetStockObject( WHITE_BRUSH );
wcexContent.lpszClassName = classNameContent;
::RegisterClassExW( &wcexContent );
With the window classes registered we can move on and create an instance of each. Note that the content window is initially zero-sized. The actual size is calculated in the parent's WM_SIZE handler further down.
// Create main window
HWND hWndMain = ::CreateWindowW( classNameMain,
L"Constant AR",
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
CW_USEDEFAULT, CW_USEDEFAULT, 800, 800,
NULL,
NULL,
hInstance,
NULL );
// Create content window
g_hWndContent = ::CreateWindowW( classNameContent,
NULL,
WS_CHILD | WS_VISIBLE,
0, 0, 0, 0,
hWndMain,
NULL,
hInstance,
NULL );
The remainder is boilerplate Windows application code:
// Show application
::ShowWindow( hWndMain, nCmdShow );
::UpdateWindow( hWndMain );
// Main message loop
MSG msg = { 0 };
while ( ::GetMessageW( &msg, NULL, 0, 0 ) > 0 )
{
::TranslateMessage( &msg );
::DispatchMessageW( &msg );
}
return (int)msg.wParam;
}
The behavior for a window class is implemented inside it's Window Procedure:
LRESULT CALLBACK WndProcMain( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) {
switch ( message ) {
case WM_CLOSE:
::DestroyWindow( hWnd );
return 0;
case WM_DESTROY:
::PostQuitMessage( 0 );
return 0;
default:
break;
In addition to standard message handling, the main window's window procedure resizes the content to fit whenever the main window's size changes:
case WM_SIZE: {
const SIZE ar = { 800, 600 };
// Query new client area size
int clientWidth = LOWORD( lParam );
int clientHeight = HIWORD( lParam );
// Calculate new content size
int contentWidth = ::MulDiv( clientHeight, ar.cx, ar.cy );
int contentHeight = ::MulDiv( clientWidth, ar.cy, ar.cx );
// Adjust dimensions to fit inside client area
if ( contentWidth > clientWidth ) {
contentWidth = clientWidth;
contentHeight = ::MulDiv( contentWidth, ar.cy, ar.cx );
} else {
contentHeight = clientHeight;
contentWidth = ::MulDiv( contentHeight, ar.cx, ar.cy );
}
// Calculate offsets to center content
int offsetX = ( clientWidth - contentWidth ) / 2;
int offsetY = ( clientHeight - contentHeight ) / 2;
// Adjust content window position
::SetWindowPos( g_hWndContent,
NULL,
offsetX, offsetY,
contentWidth, contentHeight,
SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER );
return 0;
}
}
return ::DefWindowProcW( hWnd, message, wParam, lParam );
}
The content window's window procedure doesn't implement any custom behavior, and simply forwards all messages to the default implementation:
LRESULT CALLBACK WndProcContent( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) {
return ::DefWindowProcW( hWnd, message, wParam, lParam );
}

How to properly handle a win32 GUI message loop?

I'm making a simple text editor win32 application for fun. I'm having a peculiar problem with my program. It seems that my program is not returning zero when it exits. Instead, it is returning 1385929. When my main GUI window is destroyed, I use PostQuitMessage( 0 ), but it seems that is not what is being returned in my main function's message.wParam. Here is my code thus far,
#define WIDTH 500
#define HEIGHT 400
#define EDIT_ID 10
LRESULT CALLBACK windowProc( HWND window, UINT message, WPARAM wParam, LPARAM lParam )
{
static HDC deviceContext = INVALID_HANDLE_VALUE;
static HWND editControl = INVALID_HANDLE_VALUE;
switch ( message )
{
case WM_CREATE :
deviceContext = GetDC( window );
if ( !deviceContext )
{
showWindowsError( "Creating Device Context", FALSE );
DestroyWindow( window );
}
editControl = CreateWindow(
"EDIT",
NULL,
WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_LEFT |
ES_MULTILINE | ES_AUTOVSCROLL | ES_NOHIDESEL,
0,
0,
0,
0,
window,
( HMENU )EDIT_ID,
( HINSTANCE )GetWindowLong( window, GWL_HINSTANCE ),
NULL
);
if ( !editControl )
{
showWindowsError( "Creating Edit Control", TRUE );
DestroyWindow( window );
}
return 0;
break;
case WM_COMMAND :
switch ( wParam )
{
case WM_UNDO :
SendMessage( editControl, WM_UNDO, 0, 0 );
break;
case WM_CUT :
SendMessage( editControl, WM_CUT, 0, 0 );
break;
case WM_COPY :
SendMessage( editControl, WM_COPY, 0, 0 );
break;
case WM_PASTE :
SendMessage( editControl, WM_PASTE, 0, 0 );
break;
case WM_CLEAR :
SendMessage( editControl, WM_CLEAR, 0, 0 );
break;
default:
return DefWindowProc( window, message, wParam, lParam );
}
case WM_SIZE :
MoveWindow( editControl, 0, 0, LOWORD( lParam ), HIWORD( lParam ), TRUE );
return 0;
break;
case WM_DESTROY :
ReleaseDC( window, deviceContext );
DestroyWindow( editControl );
PostQuitMessage( 0 );
return 0;
break;
}
return DefWindowProc( window, message, wParam, lParam );
}
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR CmdArgs, int nCmdShow )
{
WNDCLASSEX windowClass = { 0 };
HWND window = INVALID_HANDLE_VALUE;
MSG message = { 0 };
HBRUSH windowColor = CreateSolidBrush( GetSysColor( COLOR_WINDOW ) );
windowClass.cbSize = sizeof( windowClass );
windowClass.style = CS_HREDRAW | CS_VREDRAW;
windowClass.lpfnWndProc = windowProc;
windowClass.hInstance = hInstance;
windowClass.hCursor = LoadCursor( NULL, IDC_ARROW );
windowClass.hIcon = LoadIcon( NULL, IDI_APPLICATION );
windowClass.hbrBackground = windowColor;
windowClass.lpszClassName = "TextEditorWindow";
if ( !RegisterClassEx( &windowClass ) )
{
DeleteObject( windowColor );
showWindowsError( "Registering Windows Class", TRUE );
}
window = CreateWindow(
"TextEditorWindow",
"Text Editor",
WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
CW_USEDEFAULT,
CW_USEDEFAULT,
WIDTH,
HEIGHT,
NULL,
NULL,
hInstance,
NULL
);
if ( !window )
{
DeleteObject( windowColor );
showWindowsError( "Creating GUI", TRUE );
}
ShowWindow( window, SW_SHOW );
UpdateWindow( window );
do
{
TranslateMessage( &message );
DispatchMessage( &message );
} while ( GetMessage( &message, window, 0, 0 ) > 0 );
DeleteObject( windowColor );
return message.wParam;
}
Your call to GetMessage() has the 2nd parameter set to your window's HWND, which limits the messages received only to those sent to that window - see the documentation of the API function.
WM_QUIT is, on the other hand, a message sent to the thread running the message pump, without any particular window. Because of that filter, you don't receive it and message.wParam is never set to that 0.
But why does the loop end and the program shuts down anyway? Because that HWND in window gets invalid after the window is closed, therefore GetMessage() ends with an error and returns -1.
Additionally, you are currently calling TranslateMessage() and DispatchMessage() with message before it is filled with any correct data, on the first iteration. The loop should rather be like this:
while ( GetMessage( &message, NULL, 0, 0 ) > 0 )
{
TranslateMessage( &message );
DispatchMessage( &message );
}

Win32 Toolbar and TBSTYLE_WRAPABLE

I have a toolbar which doesn't wrap on WM_SIZE message to its parent. Here is create code for toolbar:
// create toolbar
g_hTool = CreateWindowEx( 0, TOOLBARCLASSNAME, NULL,
WS_CHILD | WS_VISIBLE | TBSTYLE_WRAPABLE, 0, 0, 0, 0,
hWnd, ( HMENU )IDC_TEX_TOOL, GetModuleHandle( NULL ), NULL );
// Send the TB_BUTTONSTRUCTSIZE message, which is required for backward compatibility.
SendMessage( g_hTool, TB_BUTTONSTRUCTSIZE, ( WPARAM )sizeof( TBBUTTON ), 0 );
SendMessage( g_hTool, TB_SETBUTTONSIZE, 0, MAKELPARAM( 32, 32 ) );
SendMessage( g_hTool, TB_SETBITMAPSIZE, 0, MAKELPARAM( 32, 32 ) );
SendMessage( g_hTool, TB_SETEXTENDEDSTYLE, 0, ( LPARAM )TBSTYLE_EX_DRAWDDARROWS );
here is WM_SIZE( handled by parent window ):
switch( uMsg ):
{
...
case WM_SIZE:
{
// get auxiliary viewport toolbar window handle and autosize
SendMessage( g_hTool, TB_AUTOSIZE, 0, 0 );
RECT cr;
GetWindowRect( g_hTool, &cr );
nTexToolHeight = cr.bottom - cr.top;
// get status bar window handle and autosize
SendMessage( g_hStatus, WM_SIZE, 0, 0 );
// get status bar height
GetWindowRect( g_hStatus, &cr );
nTexStatusHeight = cr.bottom - cr.top;
break;
}
...
}
any idea why the toolbar won't wrap? The buttons extend beyond the extents of the parent window. The buttons that extend beyond the window are clipped but the toolbar isn't resized and the buttons remain unseen...

tabs don't work when I am losing focus

I have a GUI consists of 3 tab control
when I click on each tab the controls on that tab appears (there is a dialog for each tab that I show when that tab clicked)
the application has another dialog, when I change the focus on that dialog or any other window or program and return back to the main program I just can see the tab I left before and when I click the other tabs they don't show up.
I initialize tabs in WM_INITDIALOG and I show when each one is clicked in WM_NOTIFY like this:
case WM_NOTIFY:
switch (((LPNMHDR)lParam)->code)
{
case TCN_SELCHANGING:
{
// Return FALSE to allow the selection to change.
return FALSE;
}
break;
case TCN_SELCHANGE:
{
if( TabCtrl_GetCurSel( ( ( LPNMHDR ) lParam) -> hwndFrom ) == 0 ) {
ShowWindow( hwndTimeFrame, SW_HIDE );
ShowWindow( hwndAR, SW_HIDE );
ShowWindow( hwndInsFeed, SW_SHOW );
}
if( TabCtrl_GetCurSel( ( ( LPNMHDR ) lParam) -> hwndFrom ) == 1 )
{
ShowWindow( hwndInsFeed, SW_HIDE );
ShowWindow( hwndAR, SW_HIDE );
ShowWindow( hwndTimeFrame, SW_SHOW );
}
if( TabCtrl_GetCurSel( ( ( LPNMHDR ) lParam) -> hwndFrom ) == 2 )
{
ShowWindow( hwndInsFeed, SW_HIDE );
ShowWindow( hwndTimeFrame, SW_HIDE );
ShowWindow( hwndAR, SW_SHOW );
}
}
break;
}
break;
any suggestion ?
I think I figured out this.
I initialized the tab in WM_INITDIALOG which turned out to be the problem, because each time the application showing the tab dialogs it send this message and initialize them again. I remove this part from initdialog to initialization of the application before entering the message loop