How can I make integer to display in window? - winapi

I want to have in window something like:
int a;
cout<<a;
but I don't know how I can do it. At the beginning, I want to have number displayed on screen and have a button which adds +1 and another button which adds -1 to this number. I want this number to be updated without next compilation. Do you know how I can do it?
I want it to be a prototype of simple calculator.

You can do your calculation in your corresponding button handler and set the "screen's" text with SetWindowText message.
The idea is following:
You have 2 buttons-one to add and one to subtract. You can create them in your WM_CREATE handler like this:
case WM_CREATE:
{
HWND btnAdd = CreateWindowEx( 0, L"Button",
L"+1", //this is the text for your adding button
WS_CHILD | WS_VISIBLE | WS_BORDER | BS_PUSHBUTTON,
50, 150, 150, 25, hWnd, (HMENU)8004, hInst, 0 );
HWND btnSubtract = CreateWindowEx( 0, L"Button",
L"-1", //this is the text for your adding button
WS_CHILD | WS_VISIBLE | WS_BORDER | BS_PUSHBUTTON,
50, 250, 150, 25, hWnd, (HMENU)8005, hInst, 0 );
// since you want "calculator type" application
// here is your result window-edit control
HWND input = CreateWindowEx( 0, L"Edit",
L"", // no need for text
WS_CHILD | WS_VISIBLE | WS_BORDER | ES_NUMBER | ES_AUTOHSCROLL,
50, 450, 150, 25, hWnd, (HMENU)8006, hInst, 0 );
HWND result = CreateWindowEx( 0, L"Edit",
L"", // no need for text
WS_CHILD | WS_VISIBLE | WS_BORDER | ES_READONLY | ES_AUTOHSCROLL,
50, 450, 150, 25, hWnd, (HMENU)8007, hInst, 0 );
// other stuff
}
return 0L;
After user clicks on your buttons you set text of the result edit control with SetWindowText like this in your WM_COMMAND handler:
case 8004: // add 1 to the number
{
// get the number from input edit control
wchar_t temp[10];
GetWindowText( GetDlgItem( hWnd, 8006 ), temp, 10 );
//convert text to nubmer
int InputedNumber = wtoi( temp );
// show the result in the result edit control
memset( temp, L'\0', sizeof(temp) ); //reuse variable to save memory
swprintf_s( temp, 10, L"%d", InputNumber+1 ); //convert result to text
SetWindowText( GetDlgItem( hWnd, 8007 ), temp ); //show the result
}
case 8005: // subtract 1 to the number
{
// get the number from input edit control
wchar_t temp[10];
GetWindowText( GetDlgItem( hWnd, 8006 ), temp, 10 );
//convert text to number
int InputedNumber = wtoi( temp );
// show the result in the result edit control
memset( temp, L'\0', sizeof(temp) ); //reuse variable to save memory
swprintf_s( temp, 10, L"%d", InputNumber-1 ); //convert result to text
SetWindowText( GetDlgItem( hWnd, 8007 ), temp ); //show the result
}
Above were relevant code snippets for C++.
This might be a big bite for you to handle, so I recommend you to go through this beginner tutorial.
Good luck and best regards!

Related

How to set the scroll bar for a listbox at runtime properly?

I created a lsitbox this way:
HWND hLstBx = CreateWindowEx(WS_EX_CLIENTEDGE, "Listbox", NULL, WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL, 10, 10, 300, 500, hWnd, (HMENU)ID_LSTBX, (HINSTANCE)GetWindowLong(GWL_HINSTANCE, hWnd), NULL;
//SendMessage(hLstBx, LB_SETHORIZONTALEXTENT, (WPARAM)1000, 0);
Above It creates successfully a horizontal scroll bar but what I want:
How to set the value at runtime depending on the item with the longest length?
Please don't say something like in MFC but only win32.
Thank you in advance.
There is no free lunch here, if you want to call LB_SETHORIZONTALEXTENT or LB_SETCOLUMNWIDTH you have to measure the text of each item yourself to figure out the correct pixel size.
Each time an item is added/deleted or the controls font is changed you need to measure each item. Select the controls font (WM_GETFONT) into a HDC and use GetTextExtentPoint32 or DrawText(..., DT_CALCRECT) to measure the text. You probably also want to add some padding, (2 * GetSystemMetrics(SM_CXEDGE)) perhaps and account for the vertical scrollbar (if it is visible). You can optimize this by using LB_SETITEMDATA/LB_GETITEMDATA to cache the widths so you only have to calculate the size of a new item when it is added.
Once you know the widths of all items you can set the extent to the largest item.
UINT CalcLBItemWidth(HWND hLB, LPCTSTR Text)
{
RECT r;
HDC hLBDC = GetDC(hLB);
HDC hDC = CreateCompatibleDC(hLBDC);
HFONT hFont = (HFONT) SendMessage(hLB, WM_GETFONT, 0, 0);
HGDIOBJ hOrgFont = SelectObject(hDC, hFont);
ZeroMemory(&r, sizeof(r));
DrawText(hDC, Text, -1, &r, DT_CALCRECT|DT_SINGLELINE|DT_NOCLIP);
SelectObject(hDC, hOrgFont);
DeleteDC(hDC);
ReleaseDC(hLB, hLBDC);
return (r.right - r.left) + (2 * GetSystemMetrics(SM_CXEDGE));
}
static LRESULT CALLBACK MainWndProc(HWND hWnd, UINT Msg, WPARAM wp, LPARAM lp)
{
switch(Msg)
{
case WM_CREATE:
{
HWND hLB = CreateWindowEx(WS_EX_CLIENTEDGE, WC_LISTBOX, NULL, WS_CHILD|WS_VISIBLE|WS_HSCROLL|WS_VSCROLL|LBS_NOINTEGRALHEIGHT|LBS_DISABLENOSCROLL, 10, 10, 200, 100, hWnd, (HMENU)666, g_hInst, NULL);
static const LPCTSTR strings[] = { TEXT("Foo"), TEXT("Foo bar"), TEXT("Foo bar baaaaaaaaaaaaaaaz") };
UINT largest = 0;
for (UINT i = 0; i < 33; ++i)
{
UINT temp = CalcLBItemWidth(hLB, strings[i%3]);
if (temp > largest) largest = temp;
SendMessage(hLB, LB_ADDSTRING, 0, (LPARAM) strings[i%3]);
}
SendMessage(hLB, LB_SETHORIZONTALEXTENT, largest, 0);
}
break;
...
There is a MFC example of this here that subclasses the control and does all of it for you but there is nothing MFC specific that prevents you from doing the same in plain win32...

How to set size and position of a MDI Client?

It seems like both size (x, y) and position (nWidth, nHeight) arguments are ignored when using CreateWindow. For example:
CreateWindow(L"MDICLIENT", L"", WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,
150, 10, 400, 300, hWnd, NULL, hInst, (LPVOID)&ccs);
It's always aligned to the top-left corner and takes the parent's size, as shown below.
(We could see the difference since the window background is COLOR_WINDOW).
The coordinates for MDICLIENT have no effect on start up. Instead you have to handle client-size in WM_SIZE as follows:
LRESULT CALLBACK FrameWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HWND hwndClient;
switch (message)
{
case WM_CREATE:
{
hwndClient = CreateWindow(L"MDICLIENT", L"", WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,
0, 0, 0, 0, hWnd, NULL, hInst, (LPVOID)&ccs);
...
return 0;
}
case WM_SIZE:
{
RECT rc;
GetClientRect(hwnd, &rc);
SetWindowPos(hwndToolbar, 0, 0, 0, rc.right, 30, SWP_SHOWWINDOW);
int x = 50; //right-edge of another toolbar...
int y = 30;
int w = rc.right - x;
int h = rc.bottom - y;
MoveWindow(hwndClient, x, y, w, h, 0);
return 0;
}
...
}
By the way, you won't really see any difference on the screen unless you add MDI child. The MDI child will limit its movements to the new area, it won't go over the toolbar.

Check outside click in WinApi

I'm writing application in raw WinApi using C++. I'm writing my own controls from begining. I need to get information when mouse button is click outside specific HWND. Is there any build in mechanism in WinApi to do such things or maybe I need to write my own logic?
#define IDM_FILE_NEW 21
#define IDM_FILE_OPEN 44
#define IDM_FILE_QUIT 88
case WM_RBUTTONUP:
{
HNENU hMenu;
POINT point;
point.x = LOWORD(lParam);
point.y = HIWORD(lParam);
hMenu = CreatePopupMenu();
ClientToScreen(hwnd, &point);
AppendMenuW(hMenu, MF_STRING, IDM_FILE_NEW,
L"&New");
AppendMenuW(hMenu, MF_STRING, IDM_FILE_OPEN,
L"&Open");
AppendMenuW(hMenu, MF_SEPARATOR, 0, NULL);
AppendMenuW(hMenu, MF_STRING, IDM_FILE_QUIT,
L"&Quit");
TrackPopupMenu(hMenu, TPM_RIGHTBUTTON,
point.x, point.y, 0, hwnd, NULL);
DestroyMenu(hMenu);
}
break;

child window blinking

My application is dll which is injected into 3rd party GUI application. There dll creates child window containing few controls on the main window of the application. The problem is that my window and its controls blink when the main window is redrawn. I've already read many articles about similar problems but could not fix it. Here is some code
hwndContainer = CreateWindowEx( WS_EX_TOPMOST, PANEL_CLASS_NAME, "", WS_CHILD | WS_VISIBLE, 0, 0, width, height, hwnd, 0, g_hInstance, cd );
CreateWindowEx( WS_EX_TOPMOST, "button", "Click me", WS_CHILD | WS_VISIBLE | WS_TABSTOP, x, y, w, h, hwndContainer, 0, 0, 0 );
...
case WM_PAINT:
PAINTSTRUCT ps;
HDC hdc = BeginPaint( hwndPanel, &ps );
RECT r;
GetClientRect( hwndPanel, &r );
SelectObject( hdc, hpenBorder );
SelectObject( hdc, GetStockObject( NULL_BRUSH ) );
RoundRect( hdc, 0, 0, r.right, r.bottom, 5, 5 );
EndPaint( hwndPanel, &ps );
return 0;
I tried adding WS_CLIPCHILDREN to the main window style, processed WM_PAINT of the main window etc. Any thoughts?
You may give WS_CLIPSIBLINGS a try... It's been a long time since I've done anything with window styles directly but I seem to remember this style required to help reduce redraw flicker in non-top level windows. Good luck.

How to create small window (32x32) on Windows?

Here is how the window was created. But when I GetClientRect, the rcClient is much bigger than 32x32.
int nDefaultWidth = 32;
int nDefaultHeight = 32;
UINT32 winStyle = 0;
RECT rc;
SetRect( &rc, 0, 0, nDefaultWidth, nDefaultHeight );
AdjustWindowRect( &rc, winStyle, ( hMenu != NULL ) ? true : false );
// Create the render window
HWND hWnd = CreateWindow( L"Direct3DWindowClass", NULL, winStyle,
x, y, ( rc.right - rc.left ), ( rc.bottom - rc.top ), 0,
hMenu, hInstance, 0 );
RECT rcClient;
GetClientRect( hWnd, &rcClient );
You are passing 0 as the dwStyle parameter to AdjustWindowRect. That value is equal to WS_OVERLAPPED, and AdjustWindowRect explicitly forbids you to pass that specific value.
Since you want to create a 32x32 window (i.e. with no chrome at all, pure client area) you should lose the AdjustWindowRect call as it serves no purpose at all and pass WS_POPUP as the window style to CreateWindow.

Resources