I am developing an Win32 application where user logins when the application starts in a login window and then the main window opens
But when I run the program nothing appears.
Here's the code
HINSTANCE ghInstance;
HWND hWnd;
HWND hWndPopUp;
LRESULT WINAPI PopUpWndProc( HWND hWnd2, UINT msg, WPARAM wParam, LPARAM lParam );
LRESULT WINAPI MainWndProc( HWND hWnd , UINT msg , WPARAM wParam , LPARAM lParam );
int WINAPI WinMain(HINSTANCE hInstance , HINSTANCE hPrevInstance , LPSTR lpszCmdLine , int nCmdShow){
WNDCLASS wc;
WNDCLASS wcPopUp;
MSG msg;
//HWND hWnd;
BOOL bRet;
if( !hPrevInstance )
{
wc.lpszClassName = L"MainAppClass" ;
wc.lpfnWndProc = MainWndProc ;
wc.style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW ;
wc.hInstance = hInstance ;
wc.hIcon = LoadIcon( NULL, IDI_APPLICATION ) ;
wc.hCursor = LoadCursor( NULL, IDC_ARROW ) ;
wc.hbrBackground = (HBRUSH)( COLOR_WINDOW+1 ) ;
wc.lpszMenuName = NULL ;
wc.cbClsExtra = 0 ;
wc.cbWndExtra = 0 ;
RegisterClass( &wc ) ;
wcPopUp.lpszClassName = L"PopUpAppClass" ;
wcPopUp.lpfnWndProc = PopUpWndProc ;
wcPopUp.style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW ;
wcPopUp.hInstance = hInstance ;
wcPopUp.hIcon = LoadIcon( NULL, IDI_APPLICATION ) ;
wcPopUp.hCursor = LoadCursor( NULL, IDC_ARROW ) ;
wcPopUp.hbrBackground = (HBRUSH)( COLOR_WINDOW+1 ) ;
wcPopUp.lpszMenuName = NULL ;
wcPopUp.cbClsExtra = 0 ;
wcPopUp.cbWndExtra = 0 ;
RegisterClass( &wcPopUp );
}
ghInstance = hInstance;
hWndPopUp = CreateWindowEx(WS_EX_CONTEXTHELP,
wcPopUp.lpszClassName,
L"Stock Ticker Login",
WS_OVERLAPPEDWINDOW,
0,
0,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
);
bool show = ShowWindow( hWndPopUp, SW_MAXIMIZE ) ;
UpdateWindow(hWndPopUp);
hPE = NULL;
/** While there is no WM_QUIT message in the Message Queue
Fetch Message from the queue and Dispatch it to WindowProc()
**/
while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0 )
{
if (bRet == -1)
{
// handle the error and possibly exit
int nerror = GetLastError();
MessageBox(hWnd,L"Window Error",L"Window error", MB_ICONERROR);
exit(1);
}
else {
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
return (int)msg.wParam;
}
LRESULT WINAPI PopUpWndProc( HWND hWnd2, UINT msg, WPARAM wParam, LPARAM lParam ){
HDC hdc;
PAINTSTRUCT ps;
RECT rc;
GetClientRect(hWnd, &rc);
int height = rc.bottom - rc.top;
int width = rc.right -rc.left;
switch( msg )
{
case WM_CREATE:
hWndStaticUsername = CreateWindowEx( 0
, L"static"
, L"Username"
, WS_CHILD | WS_VISIBLE
, rc.left + width/8
, rc.top + height/4
, 100
, 30
, hWnd2
, 0
, ghInstance
, 0
);
hWndEditUsername = CreateWindowEx( WS_EX_CLIENTEDGE
, L"edit"
, L""
, WS_CHILD | WS_VISIBLE
, rc.left + width/8 + 150
, rc.top + height/4
, 150
, 30
, hWnd2
, 0
, ghInstance
, 0
);
hWndBtnLogin = CreateWindowEx( 0
, L"button"
, L"Login"
, WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON
, rc.left + width/8
, rc.top + height/4 + 80
, 50
, 30
, hWnd2
, 0
, ghInstance
, 0
);
break;
case WM_COMMAND:
if(HIWORD(wParam)== BN_CLICKED && lParam==(LPARAM)hWndBtnLogin )
{
TCHAR* uname =new TCHAR;
Edit_GetText(hWndEditUsername, uname, 20);
if(wcscmp(uname,L"")==0)
return 0;
else
{
StartTicker(uname);
DestroyWindow(hWnd);
}
}
break;
case WM_DESTROY:
hWnd = CreateWindowEx(WS_EX_CONTEXTHELP,
L"MainAppClass",
L"Assignment 2",
WS_OVERLAPPEDWINDOW,
0,
0,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
ghInstance,
NULL
);
ShowWindow( hWnd, SW_MAXIMIZE ) ;
UpdateWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, msg, wParam, lParam );
}
return 0;
}
Please help me find the solution.
return DefWindowProc(hWnd, msg, wParam, lParam );
Wrong window handle, it should be hWnd2.
To uplift this post beyond a 'debug my code for me' answer, there are two fundamental things you do wrong, they are going to get you into a lot more trouble:
too sloppy on picking good variable names. You should never have a global variable named "hWnd". That should of course be hWndMain, you'd have never made that mistake.
no error check whatsoever. If you had any, you would have quickly discovered that CreateWindowEx() returned NULL and GetLastError() returned 1400. Without error checking, you can only watch it misbehave but never diagnose it.
Using the raw winapi requires meticulous attention to such small details. Consider using a class library instead.
how come you are calling:
ShowWindow( hWnd, SW_MAXIMIZE ) ;
UpdateWindow(hWnd);
only after and in the scope of: case WM_DESTROY:
I would imagine you call ShowWindow in normal execution and not in the distruction :)
Related
My application has a toolbar type menu. I sub-classed the window procedure to allow visual enhancement, which means my application is painting the menubar. When the application window is minimized and restored, the menu repaints just fine.
But, if the system colors are changed while the application window is minimized, then the menubar disappears when the application window is restored. I found that when system colors change while the application window is minimized, WM_PAINT is not sent to the menubar after the window is restored.
I tried the following:
Force sending WM_PAINT to the menubar by calling InvalidateRect() in response to WM_SIZE, but it did not cause a WM_PAINT to be sent.
Force sending WM_PAINT to the menubar by calling RedrawWindow() with the RDW_INTERNALPAINT flag. It succeeded in sending WM_PAINT, and the procedure for painting the menu is called. But still the menu does not show.
Restore the window when the system colors change, by calling ShowWindow() in response to WM_SYSCOLORCHANGE. It worked. WM_PAINT is sent to the menubar and the menu shows up. However, I think it is rude to cause my window to popup suddenly, interrupting whatever the user is doing with some other program.
Can anyone advise me how to keep the menubar painting correctly without restoring the window?
Below is how I tried to do it.
In the main window procedure:
LRESULT CALLBACK DlgWndProc (HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam)
{
static int HighContrastOn ;
static HWND hwndMenuBar ;
static HINSTANCE hThisInst ;
static NMTOOLBAR nmtb = { NULL , IDC_MENUBAR , TBN_DROPDOWN , 0 } ;
static HIGHCONTRAST HighContrast = { sizeof (HIGHCONTRAST) , 0 , 0 } ;
switch (msg) {
case WM_CREATE :
hThisInst = ((LPCREATESTRUCT) lParam)->hInstance ;
SystemParametersInfo (SPI_GETHIGHCONTRAST,0,&HighContrast,0) ;
HighContrastOn = HighContrast.dwFlags & HCF_HIGHCONTRASTON ;
return 0 ;
case WM_DESTROY :
PostQuitMessage (0) ;
return 0 ;
case WM_CLOSE :
DestroyMenu (hMenu) ;
DestroyWindow (hDlg);
return 0 ;
case WM_SYSCOLORCHANGE :
ShowWindow (hDlg,SW_NORMAL) ;
SendMessage (hwndMenuBar,WM_SYSCOLORCHANGE,0,0) ;
return 0 ;
case WM_SETTINGCHANGE :
// Catch change in HighContrast status missed by WM_SYSCOLORCHANGE
SystemParametersInfo (SPI_GETHIGHCONTRAST,0,&HighContrast,0) ;
if (HighContrastOn == (HighContrast.dwFlags & HCF_HIGHCONTRASTON))
return 0 ;
HighContrastOn = HighContrast.dwFlags & HCF_HIGHCONTRASTON ;
SendMessage (hwndMenuBar,WM_SYSCOLORCHANGE,0,0) ;
return 0 ;
case WM_NOTIFY :
OnNotify (hDlg,wParam,lParam) ;
break ;
case WM_COMMAND :
OnCommand (hDlg,wParam,lParam) ;
break ;
case WM_INITMENUPOPUP :
int SubMenu ;
SubMenu = (int) SendMessage (hwndMenuBar,TB_GETHOTITEM,0,0) ;
for (int i = 0 ; i < 5 ; i++) {
if (GetSubMenu (hMenu,i) == (HMENU) wParam)
SendMessage (hwndMenuBar,WM_INITMENUPOPUP,SubMenu,0) ;
} /* for (int i = 0 ; i < 5 ; i++) */
InitMenuPopup ((HMENU) wParam,SubMenu) ;
return 0 ;
case WM_UNINITMENUPOPUP :
int i ;
// Find out whther the closing menu is sub menu or sub-sub menu
for (i = 0 ; i < 5 ; i++) {
if ((HMENU) wParam == GetSubMenu (hMenu,i))
break ;
} /* for (i = 0 ; i < 5 ; i++) */
if (i < 5) {
UnhookWindowsHookEx (DefaultMsgHook) ;
SendMessage (hDlg,WM_NOTIFY,IDC_MENUBAR,(LPARAM) &nmtb) ;
SendMessage (hwndMenuBar,WM_UNINITMENUPOPUP,0,0) ;
} /* if (i < 5) */
return 0 ;
case IDM_INIT :
InitDialog (hDlg) ;
hMenu = LoadMenu (hThisInst,"MyProgram") ;
hwndMenuBar = GetDlgItem (hDlg,IDC_MENUBAR) ;
nmtb.hdr.hwndFrom = hwndMenuBar ;
SetWindowSubclass (hwndMenuBar,MenuBarProc,0,0) ;
SendMessage (hwndMenuBar,WM_NULL,0,0) ;
return 0 ;
} /* switch (msg) */
/* Pass unprocessed messages to DefDlgProc */
return DefDlgProc (hDlg,msg,wParam,lParam) ;
} /* DlgWndProc */
LRESULT WINAPI MenuBarMsgHook (int Code,WPARAM wParam,LPARAM lParam)
{
static NMTOOLBAR nmtb ;
switch (Code) {
case MSGF_MENU :
#define Msg ((LPMSG) lParam)
HWND hwndMenuBar ;
hwndMenuBar = GetDlgItem (Msg->hwnd,IDC_MENUBAR) ;
switch (Msg->message) {
POINT pt ;
case WM_LBUTTONDOWN :
case WM_RBUTTONDOWN :
pt = Msg->pt ;
ScreenToClient (hwndMenuBar,(LPPOINT) &pt) ;
SendMessage (hwndMenuBar,Msg->message,wParam,
(LPARAM) MAKELONG (pt.x,pt.y)) ;
break ;
case WM_MOUSEMOVE :
pt = Msg->pt ;
ScreenToClient (hwndMenuBar,(LPPOINT) &pt) ;
SendMessage (hwndMenuBar,WM_MOUSEMOVE,wParam,
(LPARAM) MAKELONG (pt.x,pt.y)) ;
break ;
} /* switch (Msg->message) */
#undef Msg
} /* switch (Code) */
return CallNextHookEx (NULL,Code,wParam,lParam) ;
} /* MenuBarMsgHook */
LRESULT CALLBACK MenuBarProc (HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam,
UINT_PTR uIdSubclass,DWORD_PTR dwRefData)
{
static bool BtnDown ;
static int HighContrastOn ;
static int yc ;
static int xr ;
static int yb ;
static int HBtn = -1 ;
static char* Text[] = {"File","Edit","Settings","Design","Help"} ;
static RECT Rect[5] ;
static HFONT Font ;
static HPEN Pen ;
static HPEN HPen ;
static HPEN SPen ;
static HBRUSH Brush ;
static HBRUSH HBrush ;
static HBRUSH SBrush ;
static COLORREF BtnTextColor = GetSysColor (COLOR_BTNTEXT) ;
static COLORREF MenuColor = GetSysColor (COLOR_MENUBAR) ;
static COLORREF HotLightColor = GetSysColor (COLOR_HOTLIGHT) ;
static COLORREF HighLightColor = GetSysColor (COLOR_HIGHLIGHT) ;
static COLORREF HiLightTextColor = GetSysColor (COLOR_HIGHLIGHTTEXT) ;
static COLORREF WindowFrameColor = GetSysColor (COLOR_WINDOWFRAME) ;
static HIGHCONTRAST HighContrast = { sizeof (HIGHCONTRAST) , 0 , 0 } ;
static TRACKMOUSEEVENT tme = {sizeof (TRACKMOUSEEVENT),TME_LEAVE,NULL,
HOVER_DEFAULT} ;
HDC hDC ;
switch (msg) {
case WM_NULL :
SystemParametersInfo (SPI_GETHIGHCONTRAST,0,&HighContrast,0) ;
HighContrastOn = HighContrast.dwFlags & HCF_HIGHCONTRASTON ;
Font = CreateMenuFont (hwnd) ;
Pen = (HPEN) GetStockObject (NULL_PEN) ;
Brush = CreateSolidBrush (MenuColor) ;
if (HighContrastOn) {
HPen = CreatePen (PS_SOLID,0,WindowFrameColor) ;
SPen = CreatePen (PS_SOLID,0,WindowFrameColor) ;
HBrush = CreateSolidBrush (HighLightColor) ;
SBrush = CreateSolidBrush (HighLightColor) ;
} /* if (HighContrastOn) */
else {
HPen = CreatePen (PS_SOLID,0,0xF87400) ;
SPen = CreatePen (PS_SOLID,0,HotLightColor) ;
HBrush = CreateSolidBrush (0xFFF4E6) ;
SBrush = CreateSolidBrush (0xFED8B0) ;
} /* else */
for (int Btn = 0 ; Btn < 5 ; Btn++)
SendMessage (hwnd,TB_GETRECT,IDM_FILEMENU + Btn,(LPARAM) (Rect + Btn)) ;
hDC = GetDC (hwnd) ;
TEXTMETRIC tm ;
GetTextMetrics (hDC,&tm) ;
ReleaseDC (hwnd,hDC) ;
yc = (Rect[0].bottom - Rect[0].top - tm.tmHeight) / 2 + tm.tmAscent - 1 ;
xr = Rect[4].right ;
yb = Rect[0].bottom ;
tme.hwndTrack = hwnd ;
return 0 ;
case WM_PAINT :
if (! GetUpdateRect (hwnd,NULL,false))
break ;
#define rc (Rect[Btn])
PAINTSTRUCT ps ;
hDC = BeginPaint (hwnd,&ps) ;
SelectObject (hDC,Font) ;
SelectObject (hDC,Pen) ;
SelectObject (hDC,Brush) ;
SetTextAlign (hDC,TA_BASELINE | TA_CENTER) ;
SetTextColor (hDC,BtnTextColor) ;
SetBkMode (hDC,TRANSPARENT) ;
for (int Btn = 0 ; Btn < 5 ; Btn++) {
Rectangle (hDC,rc.left,rc.top,rc.right,rc.bottom) ;
if (Btn == HBtn)
continue ;
int xc = (rc.right + rc.left) / 2 ;
ExtTextOut (hDC,xc,yc,ETO_NUMERICSLATIN,&rc,Text[Btn],
(UINT) strlen (Text[Btn]),NULL) ;
} /* for (int Btn = 0 ; Btn < 5 ; Btn++) */
#undef rc
#define rc (Rect[HBtn])
if (HBtn > -1) {
SelectObject (hDC,BtnDown ? SPen : HPen) ;
SelectObject (hDC,BtnDown ? SBrush : HBrush) ;
SetTextColor (hDC,HighContrastOn ? HiLightTextColor : BtnTextColor) ;
RoundRect (hDC,rc.left + 1,rc.top + 1,rc.right - 1,rc.bottom - 2,2,2) ;
int xc = (rc.right + rc.left) / 2 ;
ExtTextOut (hDC,xc,yc,ETO_NUMERICSLATIN,&rc,Text[HBtn],
(UINT) strlen (Text[HBtn]),NULL) ;
} /* if (HBtn > -1) */
#undef rc
EndPaint (hwnd,&ps) ;
return 0 ;
case WM_SYSCOLORCHANGE :
DeleteObject (HPen) ;
DeleteObject (SPen) ;
DeleteObject (Brush) ;
DeleteObject (HBrush) ;
DeleteObject (SBrush) ;
HighLightColor = GetSysColor (COLOR_HIGHLIGHT) ;
WindowFrameColor = GetSysColor (COLOR_WINDOWFRAME) ;
HotLightColor = GetSysColor (COLOR_HOTLIGHT) ;
HiLightTextColor = GetSysColor (COLOR_HIGHLIGHTTEXT) ;
BtnTextColor = GetSysColor (COLOR_BTNTEXT) ;
MenuColor = GetSysColor (COLOR_MENUBAR) ;
SystemParametersInfo (SPI_GETHIGHCONTRAST,0,&HighContrast,0) ;
HighContrastOn = HighContrast.dwFlags & HCF_HIGHCONTRASTON ;
if (HighContrastOn) {
HPen = CreatePen (PS_SOLID,0,WindowFrameColor) ;
SPen = CreatePen (PS_SOLID,0,WindowFrameColor) ;
HBrush = CreateSolidBrush (HighLightColor) ;
SBrush = CreateSolidBrush (HighLightColor) ;
} /* if (HighContrastOn) */
else {
HPen = CreatePen (PS_SOLID,0,0xF87400) ;
SPen = CreatePen (PS_SOLID,0,HotLightColor) ;
HBrush = CreateSolidBrush (0xFFF4E6) ;
SBrush = CreateSolidBrush (0xFED8B0) ;
} /* else */
Brush = CreateSolidBrush (MenuColor) ;
return 0 ;
case WM_NCDESTROY:
DeleteObject (Font) ;
DeleteObject (HPen) ;
DeleteObject (SPen) ;
DeleteObject (Brush) ;
DeleteObject (HBrush) ;
DeleteObject (SBrush) ;
RemoveWindowSubclass (hwnd,MenuBarProc,0) ;
break ;
case WM_INITMENUPOPUP :
HBtn = (int) wParam ;
BtnDown = true ;
InvalidateRect (hwnd,NULL,true) ;
break ;
case WM_UNINITMENUPOPUP :
HBtn = -1 ;
BtnDown = false ;
InvalidateRect (hwnd,NULL,true) ;
break ;
case WM_MOUSEMOVE :
#define rc (Rect[Btn])
int x ;
int y ;
x = LOWORD (lParam) ;
y = HIWORD (lParam) ;
if (HBtn > -1 && x > xr && ! BtnDown) {
HBtn = -1 ;
InvalidateRect (hwnd,NULL,true) ;
break ;
} /* if (HBtn > -1 && x > xr && ! BtnDown) */
for (int Btn = 0 ; Btn < 5 ; Btn++) {
if (y < rc.bottom && x > rc.left && x < rc.right) {
if (Btn == HBtn)
break ;
HBtn = Btn ;
InvalidateRect (hwnd,NULL,true) ;
break ;
} /* if (y < rc.bottom && x > rc.left && x < rc.right) */
} /* for (int Btn = 0 ; Btn < 5 ; Btn++) */
TrackMouseEvent (&tme) ;
#undef rc
break ;
case WM_MOUSELEAVE :
if (! BtnDown) {
HBtn = -1 ;
InvalidateRect (hwnd,NULL,true) ;
} /* if (! BtnDown) */
return 0 ;
} /* switch (msg) */
return DefSubclassProc (hwnd,msg,wParam,lParam) ;
} /* MenuBarProc */
Here is an extract of fn. InitDialog() showing initialization of menubar
#define NUMBUTTONS 5
static TBBUTTON tbButtons[NUMBUTTONS] =
{{I_IMAGENONE, IDM_FILEMENU , TBSTATE_ENABLED, BTNS_DROPDOWN | BTNS_AUTOSIZE, {0}, 0,(INT_PTR) " File"} ,
{I_IMAGENONE, IDM_EDITMENU , TBSTATE_ENABLED, BTNS_DROPDOWN | BTNS_AUTOSIZE, {0}, 0,(INT_PTR) " Edit"} ,
{I_IMAGENONE, IDM_SETTINGSMENU,TBSTATE_ENABLED, BTNS_DROPDOWN | BTNS_AUTOSIZE, {0}, 0,(INT_PTR) " Settings"} ,
{I_IMAGENONE, IDM_DESIGNMENU , TBSTATE_ENABLED, BTNS_DROPDOWN | BTNS_AUTOSIZE, {0}, 0,(INT_PTR) " Design"} ,
{I_IMAGENONE, IDM_HELPMENU , TBSTATE_ENABLED, BTNS_DROPDOWN | BTNS_AUTOSIZE, {0}, 0,(INT_PTR) " Help"}} ;
HFONT MenuFont = CreateMenuFont (hwndMenuBar) ;
SendMessage (hwndMenuBar,WM_SETFONT,(WPARAM) MenuFont,false) ;
SendMessage (hwndMenuBar,TB_BUTTONSTRUCTSIZE,(WPARAM) sizeof(TBBUTTON),0) ;
SendMessage (hwndMenuBar,TB_ADDBUTTONS, (WPARAM) NUMBUTTONS,
(LPARAM) (LPTBBUTTON) &tbButtons) ;
SendMessage (hwndMenuBar,TB_AUTOSIZE,0,0) ;
SendMessage (hwndMenuBar,TB_SETINDENT,2,0) ;
ShowWindow (hwndMenuBar,SW_SHOW) ;
SetWindowSubclass (hwndMenuBar,MenuBarProc,0,0) ;
SendMessage (hwndMenuBar,WM_NULL,0,0) ;
DeleteObject (MenuFont) ;
The menubar is defined in the dialog box resource as follows
CONTROL " ",IDC_MENUBAR,"ToolbarWindow32",TBSTYLE_FLAT | TBSTYLE_LIST | WS_CLIPCHILDREN,0,0,0,0,0,HIDC_MENUBAR
You should forward the WM_SYSCOLORCHANGE message to the toolbar control.
case WM_SYSCOLORCHANGE:
SendMessage( toolbar_hwnd, WM_SYSCOLORCHANGE, wparam, lparam );
break;
Have you sent TB_AUTOSIZE message?
SendMessage( toolbar_hwnd, TB_AUTOSIZE, 0, 0 );
Thanks to Daniel Sek, I added the line he suggested in response to WM_SIZE and it solved the problem.
case WM_SIZE :
SendMessage (hwndMenuBar,TB_AUTOSIZE,0,0) ;
return 0 ;
I did not need to call InvalidateRect () for the MenuBar. TB_AUTOSIZE msg caused WM_PAINT msg to be sent to the MenuBar and showed the menu.
Many thanks for your support.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
This is the code as attempted so far:
#include <windows.h>
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppname[] = TEXT ("win0") ;
WNDCLASS wndclass ;
MSG msg ;
HWND hwnd ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.cbWndExtra = 0 ;
wndclass.cbClsExtra = 0 ;
wndclass.lpfnWndProc = WndProc ;
wndclass.lpszClassName = szAppname ;
wndclass.lpszMenuName = NULL ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hInstance = hInstance ;
if (!RegisterClass (&wndclass))
{
MessageBox (NULL, TEXT ("Register fail"), szAppname, 0) ;
return 0 ;
}
hwnd = CreateWindow ( szAppname,
TEXT ("mywin"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL) ;
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static int cxClient, cyClient, Left, Top, Right, Down ;
PAINTSTRUCT ps ;
HDC hdc ;
RECT rect ;
Right = 20 ; Down = 20 ;
switch (message)
{
case WM_SIZE :
cxClient = LOWORD (lParam) ;
cyClient = HIWORD (lParam) ;
return 0 ;
case WM_PAINT :
hdc = BeginPaint (hwnd, &ps) ;
SetRect (&rect, Left, Top, Right, Down) ;
FillRect (hdc, &rect, CreateSolidBrush (RGB (100, 100, 100))) ;
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_KEYDOWN :
InvalidateRect (hwnd, &rect, TRUE) ;
switch (wParam)
{
case VK_UP :
if (Top - 20 < 0)
{
Top = 0 ;
Down = 20 ;
}
else
{
Top -= 20 ;
Down -= 20 ;
}
SendMessage (hwnd, WM_PAINT, wParam, lParam) ;
break ;
case VK_DOWN :
if (Down + 20 > cyClient)
{
Down = cyClient ;
Top = Down - 20 ;
}
else
{
Down += 20 ;
Top += 20 ;
}SendMessage (hwnd, WM_PAINT, wParam, lParam) ;
break ;
case VK_LEFT :
if (Left - 20 < 0)
{
Left = 0 ;
Right = 20 ;
}
else
{
Left -= 20 ;
Right -= 20 ;
}SendMessage (hwnd, WM_PAINT, wParam, lParam) ;
break ;
case VK_RIGHT :
if (Right + 20 > cxClient)
{
Right = cxClient ;
Left = Right - 20 ;
}
else
{
Right += 20 ;
Left += 20 ;
}SendMessage (hwnd, WM_PAINT, wParam, lParam) ;
break ;
default :
break ;
}
return 0 ;
case WM_DESTROY :
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam);
}
I considered that I didn't deal the message well, so I can't control it.
Apart from the fact that you should use some static variables in the Window Proc to keep your program's state (you should use the HWND as a key into key→value map to locate the right data structure), to make the window actually redraw you must "invalidate" it, i.e. tell Windows that the contents need to be redrawn. Sending a WM_PAINT message doesn't do this. InvalidateRect does, so you should call that function after changing the variables and not sending a message.
Instead you should call InvalidateRect just after setting the variables.
I have two windows, one smaller on top of other bigger. The window created first will always be on top. Neither BringWindowToTop(hWnd) nor SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); do nothing! I also have been trying HWND_TOPMOST and HWND_BOTTOM.
It seems the only way to make one window on top of other is a correct creation order. But this is not what I need, I need to change the order on the fly. Anyone knows what could cause this? Those are just old plain CreateWindow() instances both have the same parent. Any search on internet yields nothing. Need some expert help!
#include <windows.h>
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
HWND make_child(HWND Parent, int x, int y, int color) {
HINSTANCE hInstance = 0;
MSG msg = {0};
WNDCLASS wc = {0};
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.hbrBackground = CreateSolidBrush(color);//(HBRUSH)(COLOR_WINDOWFRAME);
wc.lpszClassName = (LPCSTR)L"mychildwin";
RegisterClass(&wc);
return CreateWindow("edit",(LPCSTR)"child", WS_BORDER|WS_CHILD|WS_VISIBLE, x,y,100,100,Parent,0,hInstance,NULL);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){
MSG msg = {0};
WNDCLASS wc = {0};
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.hbrBackground = CreateSolidBrush(0xff8080);
wc.lpszClassName = (LPCSTR)L"minwindowsapp";
if (!RegisterClass(&wc)) return 1;
HWND W = CreateWindow(wc.lpszClassName,(LPCSTR)L"Minimal Windows Application", WS_OVERLAPPEDWINDOW|WS_VISIBLE, 0,0,640,480,0,0,hInstance,NULL);
HWND A = make_child(W, 10, 10, 0x88ff00);
HWND B = make_child(W, 70, 70, 0x8888ff);
BringWindowToTop(B);
SetWindowPos(B, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
//REAL PROBLEM WAS HERE: A second call to SetWindowPos
SetWindowPos(handle, 0, 0, 0, new_width, new_height,
SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOACTIVATE);
// adding SWP_NOZORDER fixed it..
while(GetMessage(&msg, NULL, 0, 0) > 0) DispatchMessage(&msg);
return 0;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch(message) {
case WM_CLOSE: PostQuitMessage(0); break;
default: return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
According to the MSDN-documentation, there is also the possibility to pass a window-handle to the window you want your window to be inserted after.
BOOL WINAPI SetWindowPos(
_In_ HWND hWnd,
_In_opt_ HWND hWndInsertAfter,
_In_ int X,
_In_ int Y,
_In_ int cx,
_In_ int cy,
_In_ UINT uFlags
);
where hWndInsertAfter is the handle of the window your window shall be positioned AFTER. Have you tried this one?
Ok, maybe someone will find it really useful. Because real problem was that SetWindowPos and BringWindowToTo both worked fine, but afterwards in my real app I was calling SetWindowPos again to move the component a little, and it was screwing the ZOrder again!
So I added SWP_NOZORDER to that second call to SetWindowPos.
I want to make a screen shot and display it in the window of my program, but so far I have only been able to make the screen white.
What am I doing wrong?
Code:
#include <windows.h>
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("screen") ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
if (!RegisterClass (&wndclass))
{
MessageBox (NULL, TEXT ("Program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}
hwnd = CreateWindow (szAppName, TEXT ("Digital Clock"),
WS_POPUP|WS_DLGFRAME|WS_VISIBLE, //WS_OVERLAPPEDWINDOW| WS_MAXIMIZE,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, SW_MAXIMIZE);// iCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static BOOL f24Hour, fSuppress ;
static HBRUSH hBrushRed ;
static int cxClient, cyClient ;
HDC hdc ;
PAINTSTRUCT ps ;
TCHAR szBuffer [2] ;
HGDIOBJ hMem; // HBITMAP hMem;
HDC compdc;
switch (message)
{
case WM_CREATE:
hBrushRed = CreateSolidBrush (RGB (255, 0, 0)) ;
keybd_event(VK_SNAPSHOT, 0, KEYEVENTF_EXTENDEDKEY, 0); //get screen snapshot into clipboard
OpenClipboard(NULL);
hMem = GetClipboardData(CF_BITMAP);
case WM_SETTINGCHANGE:
return 0 ;
case WM_SIZE:
cxClient = LOWORD (lParam) ;
cyClient = HIWORD (lParam) ;
return 0 ;
case WM_TIMER:
InvalidateRect (hwnd, NULL, TRUE) ;
return 0 ;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
compdc = CreateCompatibleDC(hdc);
SelectObject(compdc,hMem);
BitBlt(hdc,0,0,cxClient,cyClient,compdc,20,20,SRCCOPY);
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_KEYDOWN:
switch(wParam)
{
case VK_ESCAPE:
DeleteObject (hBrushRed);
PostQuitMessage (0) ;
}
case WM_DESTROY:
DeleteObject (hBrushRed) ;
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
First of all, I'd avoid using the clipboard like this does -- the user should see changes in the clipboard only after an explicit cut or copy.
Instead, you should capture the contents of the screen directly. Given that you're doing this with raw Win32 calls, you'd start by defining a couple of extra variables in your WndProc:
static HBITMAP bmp;
static RECT r;
Then in your WM_CREATE handler, you'd have code something like this to actually capture the screen:
{
// First get a DC to the entire screen.
HDC s = GetDC(NULL);
// Then get the size of the screen:
r.left = GetSystemMetrics(SM_XVIRTUALSCREEN);
r.right = GetSystemMetrics(SM_CXVIRTUALSCREEN);
r.top = GetSystemMetrics(SM_YVIRTUALSCREEN);
r.bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN);
// Then create a bitmap to hold the picture of the screen:
bmp = CreateCompatibleBitmap(s, r.right, r.bottom);
// Create a memory DC and select that BMP into it:
HDC mem=CreateCompatibleDC(s);
HBITMAP old = (HBITMAP)SelectObject(mem, bmp);
// Copy the bits from the screen to our DC (and our BMP that's selected into it.
BitBlt(mem, 0, 0, r.right, r.bottom, s, 0, 0, SRCCOPY);
// Clean up:
SelectObject(mem, old);
DeleteDC(mem);
ReleaseDC(NULL, s);
}
break;
Then in your WM_PAINT handler, you'd have code like this to draw that to your window:
{
hdc = BeginPaint(hWnd, &ps);
// Create a compatible DC and select our BMP into it:
HDC mem=CreateCompatibleDC(hdc);
HBITMAP old = (HBITMAP)SelectObject(mem, bmp);
// Copy bits from our BMP to our window:
BitBlt(hdc, 0, 0, r.right, r.bottom, mem, 0, 0, SRCCOPY);
// Clean up:
SelectObject(hdc, old);
DeleteDC(mem);
EndPaint(hWnd, &ps);
break;
}
How can I make a true full screen mode in VC++?
Code:
#include <windows.h>
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("screen") ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
if (!RegisterClass (&wndclass))
{
MessageBox (NULL, TEXT ("Program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}
hwnd = CreateWindow (szAppName, TEXT ("Digital Clock"),
WS_POPUP|WS_DLGFRAME|WS_VISIBLE, // _OVERLAPPEDWINDOW| WS_MAXIMIZE,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, SW_MAXIMIZE);// iCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
Does
SetWindowPos( hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
not put it on top of the taskbar?
Check out this function and look at the definition of WS_EX_TOPMOST...
See Can a window be always on top of just one other window?
In case of multiple window set to AlwaysOnTop; than only that window will remain on top that has been manually brought on top. For instance there are two windows Window1 and Window2; then when you would run window1.exe, it would be the window on top; and when you would run window2.exe then that window would be on top, thats the default behavior.
Otherwise if you must not allow any other window to get on top, you will have to look for other apps being invoked after yours, and then probably hook those windows somehow and, well probably call its Minimize event to send it to the task bar.
Games usually use DirectX which has a mode that takes exclusive use of the video output - this means no other window (or task bar) can draw to the screen and the whole screen is available to the application at whatever resolution and colour depth you want (well almost, whatever the video card supports).