comboboxes in Windows API programming - c

I am trying to display a combobox window as you can see I set hWndComboBox as my second window and I am using ShowWindow() function and it does not really show anything when I compile and run the code? What should I add more?
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstace, LPSTR lpCommand, int nCmdLine)
{
HWND window;
int xpos = 100; // Horizontal position of the window.
int ypos = 100; // Vertical position of the window.
int nwidth = 200; // Width of the window
int nheight = 200; // Height of the window
HWND hwndParent = window; // Handle to the parent window
MSG message;
WNDCLASSEX wndClass;
wndClass.cbSize = sizeof(WNDCLASSEX);
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.style = 0;
wndClass.hInstance = hInstance;
wndClass.lpfnWndProc = wndCll;
wndClass.lpszClassName = classNoOne;
wndClass.lpszMenuName = MAKEINTRESOURCE(IDR_MYMENU);
wndClass.hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_PENGUIN_ICON));
wndClass.hIconSm = (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_PENGUIN_ICON), IMAGE_ICON, LR_DEFAULTSIZE, LR_DEFAULTSIZE, 0);
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW-1);
if(!RegisterClassEx(&wndClass)){
printf("No wndclass");
}
window = CreateWindowEx(WS_EX_CLIENTEDGE, classNoOne, "Start Window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 1000, 500, NULL, NULL, hInstance, NULL);
//create the window
HWND hWndComboBox = CreateWindow(WC_COMBOBOX, "name of the combobox", CBS_DROPDOWN | CBS_HASSTRINGS | WS_CHILD | WS_OVERLAPPED | WS_VISIBLE , xpos, ypos, nwidth, nheight, hwndParent, NULL, hInstance, NULL);
TCHAR Planets[9][10] = {
TEXT("MERCURY"), TEXT("VENUS"), TEXT("Terra"), TEXT("MARS"), TEXT("JUPITER"), TEXT("SATURN"), TEXT("URANUS"), TEXT("NEPTUNE"), TEXT("PLUTO")
};
//these are the list elements
TCHAR A[16];
int k = 0;
memset(&A, 0, sizeof(A));
//allocate memory
for(k = 0; k<=8; k+=1){
strcpy(A, (TCHAR *)Planets[k]);
SendMessage(hWndComboBox,(UINT) CB_ADDSTRING,(WPARAM) 0,(LPARAM) A);
}
SendMessage(hWndComboBox, CB_SETCURSEL, (WPARAM)2, (LPARAM)0);
ShowWindow(hWndComboBox, nCmdLine);
//ShowWindow(window, nCmdLine);
if(window == NULL){
printf("window is NULL");
}
while(GetMessage(&message, NULL, 0, 0) > 0){
if(!IsDialogMessage(dialogSmall, &message)){
TranslateMessage(&message);
DispatchMessage(&message);
}
}
return message.wParam;
}

Programming languages do not work like mathematics. In mathematics you can say x = y; and then say y = 5; and then you can infer that x must be 5.
In programming languages however, when you say HWND hwndParent = window; then hwndParent takes the value that window had at the moment of the assignment, so if you later actually initialize window with window = ... you cannot expect the value of hwndParent to suddenly become meaningful. It will stay uninitialized, since window was uninitialized at the time of the assignment.
Hint: if you have been able to do HWND hwndParent = window; when window was uninitialized, this means that you received no warning about it. Which in turn means that you have not configured your compiler to issue warnings when you do things like that. Do not try to program without warnings. You will never accomplish much this way.

Related

Calculate data from string like "1 + 1" = 2 in WinAPI C [duplicate]

This question already has answers here:
parsing math expression in c++
(6 answers)
Closed 1 year ago.
I'm currently trying to make pure WinAPI calculator that will have:
1 result textbox (where all data would be displayed)
some buttons like plus, minus, 1, 2 etc (on click, these will append text like 1,+,2 etc to Result textbox)
So now, suppose the result textbox contains string like 1 + 1, 7 / 2, 2 * 2, 8 - 8 etc, How can I invoke these strings to return data like 2, 3.5, 4, 0 respectively?
Is there any standard api in WinAPI by which I can invoke the calculation inside a string? Or do I need to make my own?
I'm using C WinAPI.
And here I got manage to complete UI and append text via buttons. Please see code:
#include <windows.h>
int IDC_result = 16;
int w = 50;
int h = 50;
void DrawButton(HWND hwnd, const char* Text, int x, int y, int code)
{
CreateWindowW(TEXT("button"), (LPCWSTR)Text, WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, x, y, w, h, hwnd, (HMENU)code, NULL, NULL);
}
const char* texts[] =
{
"7","8","9","/",
"4","5","6","*",
"1","2","3","-",
"0",".","=","+"
};
int textsLenght = (int)(sizeof(texts) / sizeof(texts[0]));
HWND RESULTS;
void DrawControls(HWND hwnd)
{
int TotalColms = 4;
RESULTS = CreateWindowEx(WS_EX_TRANSPARENT, TEXT("Edit"), TEXT(""), WS_CHILD | WS_VISIBLE | SS_LEFT | WS_SYSMENU, w * 1, h - 25, w * TotalColms, h - 30, hwnd, (HMENU)IDC_result, NULL, NULL);
int colm = 1;
int row = 1;
for(int text = 0; text < textsLenght; text++)
{
DrawButton(hwnd,texts[text],w * colm,h * row,text);
if (textsLenght / colm == TotalColms)
{
colm = 0;
row++;
}
colm++;
}
}
void appendText(LPARAM Text)
{
int Lenght = GetWindowTextLength(RESULTS);
SendMessageW(RESULTS, EM_SETSEL, Lenght, Lenght);
SendMessageW(RESULTS, EM_REPLACESEL, TRUE, Text);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
DrawControls(hwnd);
break;
case WM_COMMAND:
{
int no = LOWORD(wParam);
if (no > -1 && no < textsLenght)
{
appendText((LPARAM)texts[no]);
}
break;
}
case WM_DESTROY: PostQuitMessage(0);
default: return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
MSG msg;
WNDCLASS wc;
HWND hwnd;
ZeroMemory(&wc, sizeof wc);
wc.hInstance = hInstance;
wc.lpszClassName = L"Calculator";
wc.lpfnWndProc = (WNDPROC)WndProc;
wc.style = CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW;
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
if (FALSE == RegisterClass(&wc)) return 0;
hwnd = CreateWindowW(
L"Calculator",L"Calculator"
,WS_OVERLAPPEDWINDOW | WS_VISIBLE,CW_USEDEFAULT,CW_USEDEFAULT,
300,500
,0,0,hInstance,0);
if (NULL == hwnd) return 0;
while (GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
Please comment, if anything unclear.
Is there any standard api in winapi by which we can invoke the
calculation inside a string ? or I need to make my own ?
No there is no standard API for this; you must either make your own, or more practically find a pre-made library for this.
Another option if you want something that "just works even though it's extremely dirty/hacky/insecure" is to find a way to invoke powershell from your app and capture the output.

How to display raw array of pixels to the screen?

I am new to windows programming. I want to display the raw pixel array to the screen without using SetPixel function because it's too slow in my standards. I am using this question as my reference.
I made a small program below to fill the pixel array with random RGB values and display it to the screen. The result wasn't what I anticipated, I got the white canvas. I tried to change this line ptr++ = (b << 16) | (g << 8) | r; to ptr++ = 0x000000FF; expecting red canvas but I got the same result.
#include <stdlib.h>
#include <time.h>
#include <windows.h>
const int win_width = 500;
const int win_height = 450;
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
RECT rect;
int width, height;
COLORREF *display;
switch (msg)
{
case WM_CREATE:
srand((unsigned int) time(NULL));
GetClientRect(hWnd, &rect);
width = rect.right - rect.left;
height = rect.bottom - rect.top;
display = (COLORREF *) malloc(sizeof(COLORREF) * width * height);
COLORREF *ptr = display;
for (int y = 0; y < height; ++y)
{
for (int x = 0; x < width; ++x)
{
int r = rand() % 256;
int g = rand() % 256;
int b = rand() % 256;
*ptr++ = (b << 16) | (g << 8) | r;
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hDC, memDC;
HBITMAP hBmp, hOldBmp;
hDC = BeginPaint(hWnd, &ps);
memDC = CreateCompatibleDC(hDC);
hBmp = CreateBitmap(width, height, 1, 32, (void *) display);
hOldBmp = (HBITMAP) SelectObject(memDC, hBmp);
BitBlt(hDC, rect.left, rect.top, width, height, memDC, 0, 0, SRCCOPY);
SelectObject(memDC, hOldBmp);
DeleteObject(hBmp);
DeleteDC(memDC);
EndPaint(hWnd, &ps);
break;
}
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
const TCHAR szClassName[] = TEXT("MyClass");
WNDCLASS wc;
HWND hWnd;
MSG msg;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
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.lpszClassName = szClassName;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
if (!RegisterClass(&wc))
{
MessageBox(NULL, TEXT("Window Registration Failed!"), TEXT("Error!"),
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
hWnd = CreateWindow(szClassName,
TEXT("Random Pixels"),
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT, win_width, win_height,
NULL, NULL, hInstance, NULL);
if (hWnd == NULL)
{
MessageBox(NULL, TEXT("Window Creation Failed!"), TEXT("Error!"),
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
I know there's something wrong with my code inside WM_PAINT but I don't know how to fix it. I will appreciate any form of assistance. Thanks in advance.
The variable display that holds the pixel data has automatic lifetime. Its lifetime ends whenever control leaves WndProc. A consequence is, that every invocation of WndProc starts out with a new (indeterminate) value for display.
To solve this, display needs to have static storage duration. The easiest way to accomplish this is to replace
COLORREF *display;
with
static COLORREF *display;
This has 2 consequences:
The value stored in display survives separate invocations of WndProc.
The value stored in display is now properly zero-initialized.

win32: How to calculate control sizes for a consistent look across windows versions / themes?

Working on a simple c GUI library, I'm starting with the winapi backend and having some problems right now calculating the preferred sizes of controls. I'm comparing my results with those of Windows.Forms.
Right now, I'm using values from Design Specifications and Guidelines - Visual Design Layout (like Buttons and TextBoxes being 14 "Dialog Logical Units" high) for calculating the pixel sizes in the winapi implementation, while keeping everything default with Windows Forms. I created these simple demo implementations:
Windows Forms (demo.cs):
using System.Drawing;
using System.Windows.Forms;
namespace W32CtlTest
{
public class Demo : Form
{
private FlowLayoutPanel panel;
private Button button;
private TextBox textBox;
public Demo() : base()
{
Text = "winforms";
panel = new FlowLayoutPanel();
button = new Button();
button.Text = "test";
button.Click += (sender, args) =>
{
Close();
};
panel.Controls.Add(button);
textBox = new TextBox();
panel.Controls.Add(textBox);
Controls.Add(panel);
}
protected override Size DefaultSize
{
get
{
return new Size(240,100);
}
}
public static void Main(string[] argv)
{
if (argv.Length < 1 || argv[0] != "-s")
{
Application.EnableVisualStyles();
}
Application.Run(new Demo());
}
}
}
compile with C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe /out:demo.exe /lib:C:\Windows\Microsoft.NET\Framework\v4.0.30319 /reference:System.Windows.Forms.dll,System.Drawing.dll demo.cs
Win32 API (demo.c):
#include <string.h>
#include <windows.h>
#include <commctrl.h>
static HINSTANCE instance;
static HWND mainWindow;
static HWND button;
static HWND textBox;
#define WC_mainWindow L"W32CtlTestDemo"
#define CID_button 0x101
static NONCLIENTMETRICSW ncm;
static HFONT messageFont;
static TEXTMETRICW messageFontMetrics;
static int buttonWidth;
static int buttonHeight;
static int textBoxWidth;
static int textBoxHeight;
/* hack to enable visual styles without relying on manifest
* found at http://stackoverflow.com/a/10444161
* modified for unicode-only code */
static int enableVisualStyles(void)
{
wchar_t dir[MAX_PATH];
ULONG_PTR ulpActivationCookie = 0;
ACTCTXW actCtx =
{
sizeof(actCtx),
ACTCTX_FLAG_RESOURCE_NAME_VALID
| ACTCTX_FLAG_SET_PROCESS_DEFAULT
| ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID,
L"shell32.dll", 0, 0, dir, (LPWSTR)124,
0, 0
};
UINT cch = GetSystemDirectoryW(dir, sizeof(dir) / sizeof(*dir));
if (cch >= sizeof(dir) / sizeof(*dir)) { return 0; }
dir[cch] = L'\0';
ActivateActCtx(CreateActCtxW(&actCtx), &ulpActivationCookie);
return (int) ulpActivationCookie;
}
static void init(void)
{
INITCOMMONCONTROLSEX icx;
icx.dwSize = sizeof(INITCOMMONCONTROLSEX);
icx.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&icx);
ncm.cbSize = sizeof(ncm);
SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0);
messageFont = CreateFontIndirectW(&ncm.lfStatusFont);
HDC dc = GetDC(0);
SelectObject(dc, (HGDIOBJ) messageFont);
GetTextMetricsW(dc, &messageFontMetrics);
SIZE sampleSize;
GetTextExtentExPointW(dc,
L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
52, 0, 0, 0, &sampleSize);
ReleaseDC(0, dc);
buttonWidth = MulDiv(sampleSize.cx, 50, 4 * 52);
buttonHeight = MulDiv(messageFontMetrics.tmHeight, 14, 8);
textBoxWidth = 100;
textBoxHeight = MulDiv(messageFontMetrics.tmHeight, 14, 8);
instance = GetModuleHandleW(0);
}
static LRESULT CALLBACK wproc(HWND w, UINT msg, WPARAM wp, LPARAM lp)
{
switch (msg)
{
case WM_CREATE:
button = CreateWindowExW(0, L"Button", L"test",
WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
2, 2, buttonWidth, buttonHeight,
w, (HMENU)CID_button, instance, 0);
SendMessageW(button, WM_SETFONT, (WPARAM)messageFont, 0);
textBox = CreateWindowExW(WS_EX_CLIENTEDGE, L"Edit", L"",
WS_CHILD|WS_VISIBLE|ES_AUTOHSCROLL,
6 + buttonWidth, 2, textBoxWidth, textBoxHeight,
w, 0, instance, 0);
SendMessageW(textBox, WM_SETFONT, (WPARAM)messageFont, 0);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_COMMAND:
switch (LOWORD(wp))
{
case CID_button:
DestroyWindow(w);
break;
}
break;
}
return DefWindowProcW(w, msg, wp, lp);
}
int main(int argc, char **argv)
{
if (argc < 2 || strcmp(argv[1], "-s"))
{
enableVisualStyles();
}
init();
WNDCLASSEXW wc;
memset(&wc, 0, sizeof(wc));
wc.cbSize = sizeof(wc);
wc.hInstance = instance;
wc.lpszClassName = WC_mainWindow;
wc.lpfnWndProc = wproc;
wc.hbrBackground = (HBRUSH) COLOR_WINDOW;
wc.hCursor = LoadCursorA(0, IDC_ARROW);
RegisterClassExW(&wc);
mainWindow = CreateWindowExW(0, WC_mainWindow, L"winapi",
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 240, 100,
0, 0, instance, 0);
ShowWindow(mainWindow, SW_SHOWNORMAL);
MSG msg;
while (GetMessageW(&msg, 0, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return (int)msg.wParam;
}
compile with gcc -odemo.exe -O2 demo.c -lgdi32 -lcomctl32
The test code is also available on github
It looks like this on windows 10, with visual styles enabled in the upper row and disabled in the lower row:
One thing I soon found out is that Windows.Forms doesn't use the message font (as I had expected) but instead uses the DEFAULT_GUI_FONT Although that's not the right thing to do, I changed my win32 code accordingly so I can compare the results better:
For completeness, here is what it looks like on windows 7 without visual styles:
Now my questions are:
Is it correct to use the message font? So, Windows.Forms definitely got this one "wrong"?
Obviously Windows.Forms uses the 14 DLU height for Buttons, but some smaller height for TextBoxes. This contradicts the Design Specifications. So is Windows.Forms wrong here as well? Or should TextBoxes in fact be smaller, so the text doesn't look like it's "hanging from the ceiling"? I think this does look better the way Windows.Forms does it.
Comparing visual styles enabled/disabled, I find that without visual styles, I get the same height for my button and my text box, but with visual styles enabled on windows 10, the text box is actually higher. Is there something like "theme specific metrics" and if so, how can I use that to correct my calculations?
This is only a partial answer I'm adding here for reference:
Indeed, using the DEFAULT_GUI_FONT is wrong according to this blog entry by Raymond Chen. So, no need to trust winforms to do "the right thing".
The Design Specifications indicate that Edit Controls should be the same height as Buttons (14 DLU). To convert these to pixel sizes, the Dialog Base Units (DBU) are needed, and while GetDialogBaseUnits() only returns them for the system font, there are MSDN articles describing how to calculate them for other fonts.
1 vertical DBU corresponds to 8 DLU, so an Edit control will be 6 DLU higher than the text it contains. This doesn't look so nice, because the Edit control doesn't center the text vertically but instead aligns it at the top. winforms avoids this by calculating a smaller size for an Edit control. The drawback is that an Edit control will not align nicely next to a Button.
I found a kind of "hacky" solution to that problem by shrinking the client area of the Edit control in an overridden window proc. The following code compares the results (and contains controls using the system font for completeness):
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <commctrl.h>
typedef struct PaddedControl
{
WNDPROC baseWndProc;
int vshrink;
} PaddedControl;
static HINSTANCE instance;
static HWND mainWindow;
static HWND buttonSF;
static HWND textBoxSF;
static HWND buttonMF;
static HWND textBoxMF;
static HWND buttonMFC;
static HWND textBoxMFC;
static PaddedControl textBoxMFCPadded;
#define WC_mainWindow L"W32CtlTestDemo"
static NONCLIENTMETRICSW ncm;
static HFONT messageFont;
static TEXTMETRICW messageFontMetrics;
static int controlHeightSF;
static int controlHeightMF;
static int buttonWidthSF;
static int buttonWidthMF;
/* hack to enable visual styles without relying on manifest
* found at http://stackoverflow.com/a/10444161
* modified for unicode-only code */
static int enableVisualStyles(void)
{
wchar_t dir[MAX_PATH];
ULONG_PTR ulpActivationCookie = 0;
ACTCTXW actCtx =
{
sizeof(actCtx),
ACTCTX_FLAG_RESOURCE_NAME_VALID
| ACTCTX_FLAG_SET_PROCESS_DEFAULT
| ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID,
L"shell32.dll", 0, 0, dir, (LPWSTR)124,
0, 0
};
UINT cch = GetSystemDirectoryW(dir, sizeof(dir) / sizeof(*dir));
if (cch >= sizeof(dir) / sizeof(*dir)) { return 0; }
dir[cch] = L'\0';
ActivateActCtx(CreateActCtxW(&actCtx), &ulpActivationCookie);
return (int) ulpActivationCookie;
}
static void init(void)
{
INITCOMMONCONTROLSEX icx;
icx.dwSize = sizeof(INITCOMMONCONTROLSEX);
icx.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&icx);
ncm.cbSize = sizeof(ncm);
SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0);
messageFont = CreateFontIndirectW(&ncm.lfStatusFont);
LONG sysDbu = GetDialogBaseUnits();
HDC dc = GetDC(0);
SelectObject(dc, (HGDIOBJ) messageFont);
GetTextMetricsW(dc, &messageFontMetrics);
SIZE sampleSize;
GetTextExtentExPointW(dc,
L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
52, 0, 0, 0, &sampleSize);
ReleaseDC(0, dc);
controlHeightSF = MulDiv(HIWORD(sysDbu), 14, 8);
controlHeightMF = MulDiv(messageFontMetrics.tmHeight, 14, 8);
buttonWidthSF = MulDiv(LOWORD(sysDbu), 50, 4);
buttonWidthMF = MulDiv(sampleSize.cx, 50, 4 * 52);
instance = GetModuleHandleW(0);
}
static LRESULT CALLBACK paddedControlProc(
HWND w, UINT msg, WPARAM wp, LPARAM lp)
{
PaddedControl *self = (PaddedControl *)GetPropW(w, L"paddedControl");
WNDCLASSEXW wc;
switch (msg)
{
case WM_ERASEBKGND:
wc.cbSize = sizeof(wc);
GetClassInfoExW(0, L"Edit", &wc);
RECT cr;
GetClientRect(w, &cr);
cr.top -= self->vshrink;
cr.bottom += self->vshrink;
HDC dc = GetDC(w);
FillRect(dc, &cr, wc.hbrBackground);
ReleaseDC(w, dc);
return 1;
case WM_NCCALCSIZE:
if (!wp) break;
LRESULT result = CallWindowProcW(self->baseWndProc, w, msg, wp, lp);
NCCALCSIZE_PARAMS *p = (NCCALCSIZE_PARAMS *)lp;
int height = p->rgrc[0].bottom - p->rgrc[0].top;
self->vshrink = 0;
if (height > messageFontMetrics.tmHeight + 3)
{
self->vshrink = (height - messageFontMetrics.tmHeight - 3) / 2;
p->rgrc[0].top += self->vshrink;
p->rgrc[0].bottom -= self->vshrink;
}
return result;
}
return CallWindowProcW(self->baseWndProc, w, msg, wp, lp);
}
static LRESULT CALLBACK wproc(HWND w, UINT msg, WPARAM wp, LPARAM lp)
{
switch (msg)
{
case WM_CREATE:
buttonSF = CreateWindowExW(0, L"Button", L"sysfont",
WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
4, 4, buttonWidthSF, controlHeightSF,
w, 0, instance, 0);
buttonMF = CreateWindowExW(0, L"Button", L"msgfont",
WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
4, 8 + controlHeightSF, buttonWidthMF, controlHeightMF,
w, 0, instance, 0);
SendMessageW(buttonMF, WM_SETFONT, (WPARAM)messageFont, 0);
buttonMFC = CreateWindowExW(0, L"Button", L"msgfont adj",
WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
4, 12 + controlHeightSF + controlHeightMF,
buttonWidthMF, controlHeightMF,
w, 0, instance, 0);
SendMessageW(buttonMFC, WM_SETFONT, (WPARAM)messageFont, 0);
textBoxSF = CreateWindowExW(WS_EX_CLIENTEDGE, L"Edit", L"abcdefgh",
WS_CHILD|WS_VISIBLE|ES_AUTOHSCROLL,
8 + buttonWidthSF, 4, 100, controlHeightSF,
w, 0, instance, 0);
textBoxMF = CreateWindowExW(WS_EX_CLIENTEDGE, L"Edit", L"abcdefgh",
WS_CHILD|WS_VISIBLE|ES_AUTOHSCROLL,
8 + buttonWidthMF, 8 + controlHeightSF,
100, controlHeightMF,
w, 0, instance, 0);
SendMessageW(textBoxMF, WM_SETFONT, (WPARAM)messageFont, 0);
textBoxMFC = CreateWindowExW(WS_EX_CLIENTEDGE, L"Edit", L"abcdefgh",
WS_CHILD|WS_VISIBLE|ES_AUTOHSCROLL,
8 + buttonWidthMF, 12 + controlHeightSF + controlHeightMF,
100, controlHeightMF,
w, 0, instance, 0);
memset(&textBoxMFCPadded, 0, sizeof(PaddedControl));
textBoxMFCPadded.baseWndProc = (WNDPROC)SetWindowLongPtr(
textBoxMFC, GWLP_WNDPROC, (LONG_PTR)paddedControlProc);
SetPropW(textBoxMFC, L"paddedControl", &textBoxMFCPadded);
SetWindowPos(textBoxMFC, 0, 0, 0, 0, 0,
SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOMOVE|SWP_FRAMECHANGED);
SendMessageW(textBoxMFC, WM_SETFONT, (WPARAM)messageFont, 0);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProcW(w, msg, wp, lp);
}
int main(int argc, char **argv)
{
if (argc < 2 || strcmp(argv[1], "-s"))
{
enableVisualStyles();
}
init();
WNDCLASSEXW wc;
memset(&wc, 0, sizeof(wc));
wc.cbSize = sizeof(wc);
wc.hInstance = instance;
wc.lpszClassName = WC_mainWindow;
wc.lpfnWndProc = wproc;
wc.hbrBackground = (HBRUSH) COLOR_WINDOW;
wc.hCursor = LoadCursorA(0, IDC_ARROW);
RegisterClassExW(&wc);
mainWindow = CreateWindowExW(0, WC_mainWindow, L"fontdemo",
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 240, 180,
0, 0, instance, 0);
ShowWindow(mainWindow, SW_SHOWNORMAL);
MSG msg;
while (GetMessageW(&msg, 0, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return (int)msg.wParam;
}
The last row of controls using this hack is the best I could achieve so far:
As you can see, a problem that still persists is that the heights of Button and Edit controls look different with the visual styles theme of Windows 10. So I'd still be happy to see a better answer to this question.

Paasing A window Handle to a Thread in C. (WIN32 API)

I have created a Window and a Thread in my Application. Now I want the thread to process some data and display it on the Main Window.
For this purpose, I have used PostMessage() funcion inside my thread.
i.e. A window is created, then a Thread is created. The thread applies some processing to data and Posts a Message to Main window that data should be displayed now.
But the problem is that for this purpose, I shall have to pass Window's Handle, While for this thread, Main Window Handle is an undeclared IDENTIFIER.
Is there any possible way in which I can pass the handle to Main Window to my thread so that using this Handle, the Thread is able to Post the Message.
Below is the code snippet for any help:
///Thread Function////
DWORD WINAPI threadFunction(LPVOID param)
{
//do something
PostMessage(hMainWin, WM_thread,0, 0);
return true;
}
////Main Function///
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd )
{
const char AH_Glb_ClassName[] = "myWindClass";
WNDCLASSEX wc;
MSG Msg;
//Registering the Window Class
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = NULL;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = NULL;
wc.lpszClassName = AH_Glb_ClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
HWND hMainWin; //Handle to Main WIndow
///Creating Main Window///
hMainWin = CreateWindowEx( WS_EX_CLIENTEDGE,
AH_Glb_ClassName,
"I am SERVER Window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
440,
120,
NULL, NULL, NULL, NULL);
if(hMainWin == NULL)
{
MessageBox(NULL,
"Window Creation Failed!",
"Error!",
MB_ICONEXCLAMATION |
MB_OK);
return 0;
}
ShowWindow(hMainWin,SW_MAXIMIZE);
UpdateWindow(hMainWin);
/////////////////THREAD////////////////
DWORD threadID = 0;
///Creating Thread///
HANDLE threadHandle = CreateThread(NULL,
0,
threadFunction,
0,
0,
&threadID);
return 0;
}
DWORD WINAPI threadFunction(LPVOID param)
{
HANDLE hwnd = (HANDLE)param;
}
...
HANDLE threadHandle = CreateThread(NULL,
0,
threadFunction,
(LPVOID)hMainWin,
0,
&threadID);
Thread function has LPVOID type, it matches the HANDLE type, both in Win32 and x64.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682453%28v=vs.85%29.aspx
BTW, you need to add message loop to WinMain.

Missing ';' identifier before PVOID64

I saw another post addressing this issue however the asker was apparently including winnt.h instead of windows.h (which supposedly includes winnt.h)
I'm using windows.h but still getting this issue.
I've tried using Visual Studio 2010 Express and Ultimate and both produce this error.
Has anyone encountered this before?
Here is the code:
#include<Windows.h>
#include<d3d9.h>
#include<time.h>
#include<d3dx.h>
#define APPTITLE "Create Surface"
#define KEY_DOWN(vk_code)((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEY_UP(vk_code)((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
LRESULT WINAPI WinProc(HWND, UINT, WPARAM, LPARAM);
ATOM MyRegisterClass(HINSTANCE);
int Game_Init(HWND);
void Game_Run(HWND);
void Game_End(HWND);
LPDIRECT3D9 d3d = NULL;
LPDIRECT3DDEVICE9 d3ddev = NULL;
LPDIRECT3DSURFACE9 backbuffer = NULL, surface = NULL;
LRESULT WINAPI WinProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){
switch(msg){
case WM_DESTROY:
Game_End(hWnd);
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
ATOM MyRegisterClass(HINSTANCE hInstance){
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WinProc;
wc.cbWndExtra = 0;
wc.cbClsExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = APPTITLE;
wc.hIconSm = NULL;
return RegisterClassEx(&wc);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){
MSG msg;
MyRegisterClass(hInstance);
HWND hWnd;
hWnd = CreateWindow(
APPTITLE,
APPTITLE,
WS_EX_TOPMOST | WS_VISIBLE | WS_POPUP,
CW_USEDEFAULT,
CW_USEDEFAULT,
SCREEN_WIDTH,
SCREEN_HEIGHT,
NULL,
NULL,
hInstance,
NULL);
if(!hWnd)
return FALSE;
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
if(!Game_Init(hWnd))
return 0;
int done = 0;
while(!done){
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){
if(msg.message == WM_QUIT)
done = 1;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
Game_Run(hWnd);
}
return msg.wParam;
}
int Game_Init(HWND hWnd){
HRESULT result;
d3d = Direct3DCreate9(D3D_SDK_VERSION);
if(d3d == NULL){
MessageBox(hWnd, "Failed to initialise d3d", "Error", MB_OK);
return 0;
}
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = FALSE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.BackBufferCount = 1;
d3dpp.BackBufferHeight = SCREEN_HEIGHT;
d3dpp.BackBufferWidth = SCREEN_WIDTH;
d3dpp.hDeviceWindow = hWnd;
d3d->CreateDevice(
D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp,
&d3ddev);
if(d3ddev == NULL){
MessageBox(hWnd, "Failed to initialise Direct3D device", "Error", MB_OK);
return 0;
}
srand(time(NULL));
d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
d3ddev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
result = d3ddev->CreateOffscreenPlainSurface(
100,
100,
D3DFMT_X8R8G8B8,
D3DPOOL_DEFAULT,
&surface,
NULL);
if(!result)
return 1;
return 1;
}
void Game_Run(HWND hWnd){
RECT rect;
int r,g,b;
if(d3ddev == NULL)
return;
if(d3ddev->BeginScene()){
r = rand() % 255;
g = rand() % 255;
b = rand() % 255;
d3ddev->ColorFill(surface, NULL, D3DCOLOR_XRGB(r,g,b));
rect.left = rand() % SCREEN_WIDTH / 2;
rect.right = rect.left + rand() % SCREEN_WIDTH / 2;
rect.top = rand() % SCREEN_HEIGHT;
rect.bottom = rect.top + rand() % SCREEN_HEIGHT / 2;
d3ddev->StretchRect(surface, NULL, backbuffer, &rect, D3DTEXF_NONE);
d3ddev->EndScene();
}
d3ddev->Present(NULL, NULL, NULL, NULL);
if(KEY_DOWN(VK_ESCAPE))
PostMessage(hWnd, WM_DESTROY, 0, 0);
}
void Game_End(HWND hWnd){
surface->Release();
if(d3ddev != NULL)
d3ddev->Release();
if(d3d != NULL)
d3d->Release();
}
And the link for the post I mentioned above:
syntax error : missing ';' before identifier 'PVOID64' when compiling winnt.h
This is because the order of the VC++ include directory, try to put the path windows SDK before DirectX SDK, as below.
So I think I stumbled across a solution when trying to sort this on a different laptop.
There's something that seems to get installed with the Windows SDK called Windows SDK Configuration Tool. Running that detects which versions of the SDK you have installed then allows you to select which one to use. It then configures all versions of Visual Studio you have to use the selected version.
I think that solved the issue - not had a proper chance to fully check yet - I also uninstalled all versions of Visual Studio I had with all related components and reinstalled just the one I needed (for the time being - might install other versions later to see if that potentially cause a conflict of sorts).
Anyway, just figured I'd leave a possible solution on here for anyone that happens across this thread.
\,,/[>.<]\,,/

Resources