Why can't I seem to add buttons to a toolbar? [WINAPI] - c

For some reason, as soon as I try to separate certain blocks of code into different functions, adding buttons (bitmaps included) to a toolbar isn't working anymore. Having them put together in one place however works like a charm, however.
Yet I can't figure out the reason for this. Maybe a pointer isn't working as expected...
The expected output is this:
The relevant code:
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
CreateUserInterface(hwnd);
break;
...
}
return 0;
}
void CreateUserInterface(HWND hwnd)
{
HFONT hfDefault;
HWND hEdit;
HWND hTool;
TBADDBITMAP tbab;
TBBUTTON tbb[TBBSIZE];
HWND hStatus;
int statWidths[] = {100, -1};
// create edit control
hEdit = CreateWindowEx(WS_EX_CLIENTEDGE,
"EDIT",
"",
WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL |
ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL,
0, 0, 100, 100,
hwnd, (HMENU) IDC_MAIN_EDIT,
GetModuleHandle(NULL), NULL);
if(hEdit == NULL)
{
MessageBox(hwnd, "Could not create edit box!", "Error!",
MB_OK | MB_ICONERROR);
}
hfDefault = GetStockObject(DEFAULT_GUI_FONT);
SendMessage(hEdit, WM_SETFONT, (WPARAM) hfDefault, MAKELPARAM(FALSE, 0));
// create toolbar
hTool = CreateWindowEx(0, TOOLBARCLASSNAME, NULL,
WS_CHILD | WS_VISIBLE,
0, 0, 0, 0,
hwnd, (HMENU) IDC_MAIN_TOOL,
GetModuleHandle(NULL), NULL);
if(hTool == NULL)
{
MessageBox(hwnd, "Could not create tool bar!", "Error!",
MB_OK | MB_ICONERROR);
}
SendMessage(hTool, TB_BUTTONSTRUCTSIZE, (WPARAM) sizeof(TBBUTTON), 0);
tbab.hInst = HINST_COMMCTRL;
tbab.nID = IDB_STD_SMALL_COLOR;
SendMessage(hTool, TB_ADDBITMAP, 0, (LPARAM) &tbab);
ZeroMemory(tbb, sizeof tbb);
tbb[0].iBitmap = STD_FILENEW;
tbb[0].fsState = TBSTATE_ENABLED;
tbb[0].fsStyle = TBSTYLE_BUTTON;
tbb[0].idCommand = ID_FILE_NEW;
tbb[1].iBitmap = STD_FILEOPEN;
tbb[1].fsState = TBSTATE_ENABLED;
tbb[1].fsStyle = TBSTYLE_BUTTON;
tbb[1].idCommand = ID_FILE_OPEN;
tbb[2].iBitmap = STD_FILESAVE;
tbb[2].fsState = TBSTATE_ENABLED;
tbb[2].fsStyle = TBSTYLE_BUTTON;
tbb[2].idCommand = ID_FILE_SAVE_AS;
SendMessage(hTool, TB_ADDBUTTONS, sizeof(tbb)/sizeof(TBBUTTON), (LPARAM) &tbb);
}
What I get is:
The relevant code:
#define TBBSIZE 1
void CreateUserInterface(HWND hwnd)
{
...
HWND hTool;
TBADDBITMAP tbab;
TBBUTTON tbb[TBBSIZE];
...
CreateToolbar(hwnd, hTool);
InitializeBitmap(hTool, &tbab);
InitializeButtons(htool, tbb, TBBSIZE);
...
}
void CreateToolbar(HWND hwnd, HWND hTool)
{
hTool = CreateWindowEx(0, TOOLBARCLASSNAME, NULL,
WS_CHILD | WS_VISIBLE,
0, 0, 0, 0,
hwnd, (HMENU) IDC_MAIN_TOOL,
GetModuleHandle(NULL), NULL);
if(hTool == NULL)
{
MessageBox(hwnd, "Could not create tool bar!", "Error!",
MB_OK | MB_ICONERROR);
}
SendMessage(hTool, TB_BUTTONSTRUCTSIZE, (WPARAM) sizeof(TBBUTTON), 0);
}
void InitializeBitmap(HWND hTool, TBADDBITMAP *tbab)
{
(*tbab).hInst = HINST_COMMCTRL;
(*tbab).nID = IDB_STD_SMALL_COLOR;
SendMessage(hTool, TB_ADDBITMAP, 0, (LPARAM) tbab);
}
void InitializeButtons(HWND hTool, TBBUTTON *tbb, int size)
{
ZeroMemory(tbb, sizeof(*tbb) * size);
tbb[size-size].iBitmap = STD_FILENEW;
tbb[size-size].fsState = TBSTATE_ENABLED;
tbb[size-size].fsStyle = TBSTYLE_BUTTON;
tbb[size-size].idCommand = ID_FILE_NEW;
SendMessage(hTool, TB_ADDBUTTONS, size, (LPARAM) tbb);
...
}
(Don't mind the status bar to the bottom right, I forgot to include it in the code in the first example)
For obvious reasons the problem must lie somewhere in the bit that handles adding the bitmaps and buttons. But what it is I don't know...what am I missing?
Edit1: To make it read easier I have removed the two additional buttons (less code). It works the same way still, i.e. not working at all. ;-)
EDIT2: Thanks to HostileFork I found out that a windows handle doesn't work quite the same way as a normal raw pointer in C. The solution was to pass the address of hTool to the CreateToolbar function:
#define TBBSIZE 1
void CreateUserInterface(HWND hwnd)
{
...
HWND hTool;
...
CreateToolbar(hwnd, &hTool);
...
}
void CreateToolbar(HWND hwnd, HWND *hTool)
{
*hTool = CreateWindowEx(0, TOOLBARCLASSNAME, NULL,
WS_CHILD | WS_VISIBLE,
0, 0, 0, 0,
hwnd, (HMENU) IDC_MAIN_TOOL,
GetModuleHandle(NULL), NULL);
... // and so on
}

It looks like you're assigning to an argument, which will only affect it for the duration of the function:
void CreateToolbar(HWND hwnd, HWND hTool)
{
hTool = CreateWindowEx(0, TOOLBARCLASSNAME, NULL,
WS_CHILD | WS_VISIBLE,
0, 0, 0, 0,
hwnd, (HMENU) IDC_MAIN_TOOL,
GetModuleHandle(NULL), NULL);
...
}
You need to either make hTool a return value, or pass it by reference or pointer so that its value can be bubbled up to the caller and used in the other functions...

Does InitializeButtons have a default value for the third parameter, size? If so, check what it is, as you don't appear to be sending this value in the call to the method. My guess is that the parameter defaults to zero, so this will be passed in the SendMessage call.
If InitializeButtons doesn't have a default value for the third parameter, then either you have a typo in your example source, you have two InitializeButtons methods with different numbers of parameters (and hence are calling the wrong one), or your code shouldn't compile :)

Related

Win32 API Disable User Input in Drop Down / Combobox

This sample code I found online has a list dropdown menu, and when I click the text box that the items are displayed in, it doesn't allow me to type anything into the box. This is the behavior I want for my own code. However when I paste in the relevant parts of this code into my own, my program is allowing me to type characters into the Drop Down box. I can't find a single flag in this code that is causing the user input to be disabled, but it only works properly here and not in my code for some reason.
I even tried commenting out certain lines of the code to see if they were responsible for disabling user input, but it is still disabled. Yet in my code, no matter what I do, I can type additional characters into the list box as if it were any other text field. I can't figure out what I'm missing.
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HINSTANCE g_hinst;
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PWSTR lpCmdLine, int nCmdShow) {
HWND hwnd;
MSG msg ;
WNDCLASS wc = {0};
wc.lpszClassName = "Application";
wc.hInstance = hInstance ;
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
wc.lpfnWndProc = WndProc ;
wc.hCursor = LoadCursor(0,IDC_ARROW);
g_hinst = hInstance;
RegisterClass(&wc);
hwnd = CreateWindow(wc.lpszClassName, "Combo box",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
100, 100, 270, 170, 0, 0, hInstance, 0);
while (GetMessage(&msg, NULL, 0, 0)) {
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam) {
static HWND hwndCombo;
//static HWND hwndStatic;
const char *items[] = { "FreeBSD", "OpenBSD",
"NetBSD", "Solaris", "Arch" };
switch(msg) {
case WM_CREATE:
hwndCombo = CreateWindow("Combobox", NULL,
WS_CHILD | WS_VISIBLE | CBS_DROPDOWN,
10, 10, 120, 200, hwnd, NULL, g_hinst, NULL);
// CreateWindowW(L"Button", L"Drop down",
// WS_CHILD | WS_VISIBLE,
// 150, 10, 90, 25, hwnd, (HMENU) 1, g_hinst, NULL);
// hwndStatic = CreateWindowW(L"Static", L"",
// WS_CHILD | WS_VISIBLE,
// 150, 80, 90, 25, hwnd, NULL, g_hinst, NULL);
for (int i = 0; i < 4; i++ ) {
SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM) items[i]);
}
break;
case WM_COMMAND:
// if (HIWORD(wParam) == BN_CLICKED) {
// SendMessage(hwndCombo, CB_SHOWDROPDOWN, (WPARAM) TRUE, 0);
// }
if (HIWORD(wParam) == CBN_SELCHANGE) {
LRESULT sel = SendMessage(hwndCombo, CB_GETCURSEL, 0, 0);
// SetWindowTextW(hwndStatic, items[sel]);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProcW(hwnd, msg, wParam, lParam);
}
There is no special handling, no character limit flags, no additional source code or headers, or resource files, nothing...
I've read this code over and over and I just don't understand what is causing this program to present the dropdown items as read-only text.
My code is pretty much identical with just some additional switch statements and functions, but the functionality of the combo box should be the same. Is there some other global flag in a program that could cause user input where it shouldn't be allowed?
Use the CBS_DROPDOWNLIST style on the ComboBox to remove the writable edit control
hwndCombo = CreateWindow("Combobox", NULL,
WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST,
10, 10, 120, 200, hwnd, NULL, g_hinst, NULL);
Per the documentation:
Combo Box Styles
To create a combo box using the CreateWindow or CreateWindowEx function, specify the COMBOBOX class, appropriate window style constants, and a combination of the following combo box styles.
Constant
Description
...
...
CBS_DROPDOWN
Similar to CBS_SIMPLE, except that the list box is not displayed unless the user selects an icon next to the edit control.
CBS_DROPDOWNLIST
Similar to CBS_DROPDOWN, except that the edit control is replaced by a static text item that displays the current selection in the list box.
...
...
CBS_SIMPLE
Displays the list box at all times. The current selection in the list box is displayed in the edit control.
...
...

error LNK1120: 1 unresolved external - VS13 C [duplicate]

This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 6 years ago.
I have tried to compile this code:
#include <windows.h>
#include <commctrl.h>
#define ID_TABCTRL 1
#define ID_EDIT 2
#define BTN_ADD 3
#define BTN_DEL 4
#define BTN_CLR 5
#define MAX_TAB_LEN 15
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HWND hTab, hEdit;
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PWSTR pCmdLine, int nCmdShow) {
MSG msg;
WNDCLASSW wc = { 0 };
wc.lpszClassName = L"Tab control";
wc.hInstance = hInstance;
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
wc.lpfnWndProc = WndProc;
wc.hCursor = LoadCursor(0, IDC_ARROW);
RegisterClassW(&wc);
CreateWindowW(wc.lpszClassName, L"Tab control",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
100, 100, 380, 230, 0, 0, hInstance, 0);
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
WINCOMMCTRLAPI BOOL WINAPI InitCommonControlsEx(_In_ const INITCOMMONCONTROLSEX *picce);
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam) {
TCITEMW tie;
wchar_t text[4];
LRESULT count, id;
INITCOMMONCONTROLSEX icex;
switch (msg) {
case WM_CREATE:
icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
icex.dwICC = ICC_TAB_CLASSES;
InitCommonControlsEx(&icex);
hTab = CreateWindowW(WC_TABCONTROLW, NULL, WS_CHILD | WS_VISIBLE,
0, 0, 200, 150, hwnd, (HMENU)ID_TABCTRL, NULL, NULL);
hEdit = CreateWindowW(WC_EDITW, NULL, WS_CHILD | WS_VISIBLE | WS_BORDER,
250, 20, 100, 25, hwnd, (HMENU)ID_EDIT, NULL, NULL);
SendMessage(hEdit, EM_SETLIMITTEXT, MAX_TAB_LEN, 0);
CreateWindowW(WC_BUTTONW, L"Add", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
250, 50, 100, 25, hwnd, (HMENU)BTN_ADD, NULL, NULL);
CreateWindowW(WC_BUTTONW, L"Delete", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
250, 80, 100, 25, hwnd, (HMENU)BTN_DEL, NULL, NULL);
CreateWindowW(WC_BUTTONW, L"Clear", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
250, 110, 100, 25, hwnd, (HMENU)BTN_CLR, NULL, NULL);
break;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case BTN_ADD:
GetWindowTextW(hEdit, text, 250);
if (lstrlenW(text) != 0) {
tie.mask = TCIF_TEXT;
tie.pszText = text;
count = SendMessageW(hTab, TCM_GETITEMCOUNT, 0, 0);
SendMessageW(hTab, TCM_INSERTITEMW, count,
(LPARAM)(LPTCITEM)&tie);
}
break;
case BTN_DEL:
id = SendMessageW(hTab, TCM_GETCURSEL, 0, 0);
if (id != -1) {
SendMessageW(hTab, TCM_DELETEITEM, 0, id);
}
break;
case BTN_CLR:
SendMessageW(hTab, TCM_DELETEALLITEMS, 0, 0);
break;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return(DefWindowProcW(hwnd, msg, wParam, lParam));
}
and it seems like this libary:
#include <commctrl.h>
giving me the following error:
error LNK2019: unresolved external symbol __imp__InitCommonControlsEx#4 referenced in function _WndProc#16 C:\Users\User\Desktop\Magshimim\Magshimim EX1\Magshimim EX1\01.obj Magshimim EX1
now the code is an example code from here: http://zetcode.com/gui/winapi/advancedcontrols/
so i figured out that something wrong with my compiler...
can any one help me find the problem and correct it?
edit:
the question is not a duplicate because the refereed duplicate talks in a very general way about the error itself and as a beginner i dont have the skills to build a proper answer from such a question and because that code is been used by many peoples who check the example i think its impotent to make a specific question
Either add #pragma comment(lib, "comctl32.lib") or adjust the linker settings to link against comctl32.lib.
You can check the table at the bottom of a function's MSDN article to find out, which library you are required to link against. Every Windows application is linked against kernel32.dll and every GUI application against user32.dll. Anything else needs to be specified explicitly1.
1 There are exceptions, check IInspectable's comment below.

Same _exact_ code in C and D give different results -- why?

When I run this C code:
// Get rid of the CRT and stuff; we don't need it
#pragma comment(linker, "/Entry:mainCRTStartup")
#pragma comment(linker, "/NoDefaultLib:msvcrt.lib")
#pragma comment(linker, "/NoDefaultLib:kernel32.lib")
#pragma comment(linker, "/NoDefaultLib:ntdll.lib")
#pragma comment(linker, "/Subsystem:Console")
#pragma comment(lib, "user32.lib")
#include <windows.h>
int mainCRTStartup()
{
MSG msg;
HWND hWndParent;
WNDCLASS wndClass =
{
0, &DefWindowProc, 0, 0, NULL, NULL, LoadCursor(NULL, IDC_ARROW),
GetSysColorBrush(COLOR_3DFACE), NULL, TEXT("MyClass")
};
RegisterClass(&wndClass);
hWndParent = CreateWindow(
wndClass.lpszClassName, NULL, WS_VISIBLE | WS_OVERLAPPEDWINDOW,
0, 0, 33, 100, NULL, NULL, NULL, NULL);
CreateWindow(TEXT("Button"), wndClass.lpszClassName,
WS_VISIBLE | WS_CHILD | BS_GROUPBOX,
5, 5, 100, 50, hWndParent, NULL, NULL, NULL);
while (GetMessage(&msg, hWndParent, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
I get:
But when I run the equivalent D code:
// Again, get rid of the runtime
pragma(startaddress, mainCRTStartup);
pragma(lib, "dmd_win32.lib");
import win32.windows;
int mainCRTStartup()
{
MSG msg;
HWND hWndParent;
WNDCLASS wndClass =
{
0, &DefWindowProc, 0, 0, NULL, NULL, LoadCursor(NULL, IDC_ARROW),
GetSysColorBrush(COLOR_3DFACE), NULL, "MyClass"
};
RegisterClass(&wndClass);
hWndParent = CreateWindow(
wndClass.lpszClassName, NULL, WS_VISIBLE | WS_OVERLAPPEDWINDOW,
0, 0, 33, 100, NULL, NULL, NULL, NULL);
CreateWindow("Button", wndClass.lpszClassName,
WS_VISIBLE | WS_CHILD | BS_GROUPBOX,
5, 5, 100, 50, hWndParent, NULL, NULL, NULL);
while (GetMessage(&msg, hWndParent, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
I get:
I'm so confused... what can possibly be causing this white background?!
Edit:
I'm not sure it's actually a library bug... I just removed the dependency (and I don't see anything wrong with the code), but the problem is still there:
version = Unicode;
extern(Windows):
alias void* HWND, HMENU, HINSTANCE, HCURSOR, HBRUSH, HICON;
alias ushort ATOM, WORD;
alias uint UINT, DWORD;
alias int[2] POINT;
alias int BOOL;
alias int LONG;
alias size_t WPARAM, LPARAM, LRESULT;
alias char* LPSTR;
alias const(char)* LPCSTR;
alias wchar* LPWSTR;
alias const(wchar)* LPCWSTR;
version(Unicode)
{
alias LPCWSTR LPCTSTR;
alias LPWSTR LPTSTR;
alias GetMessageW GetMessage;
alias CreateWindowExW CreateWindowEx;
alias DispatchMessageW DispatchMessage;
alias DefWindowProcW DefWindowProc;
alias LoadCursorW LoadCursor;
alias RegisterClassW RegisterClass;
alias WNDCLASSW WNDCLASS;
}
else
{
alias LPCSTR LPCTSTR;
alias LPSTR LPTSTR;
alias GetMessageA GetMessage;
alias CreateWindowExA CreateWindowEx;
alias DispatchMessageA DispatchMessage;
alias DefWindowProcA DefWindowProc;
alias LoadCursorA LoadCursor;
alias RegisterClassA RegisterClass;
alias WNDCLASSA WNDCLASS;
}
LPCTSTR MAKEINTATOM(ATOM atom) { return cast(LPCTSTR)atom; }
ATOM RegisterClassA(WNDCLASSA*);
ATOM RegisterClassW(WNDCLASSW*);
HCURSOR LoadCursorA(HINSTANCE, LPCSTR);
HCURSOR LoadCursorW(HINSTANCE, LPCWSTR);
LRESULT DefWindowProcA(HWND, UINT, WPARAM, LPARAM);
LRESULT DefWindowProcW(HWND, UINT, WPARAM, LPARAM);
BOOL GetMessageA(const(MSG)*, HWND, UINT, UINT);
BOOL GetMessageW(const(MSG)*, HWND, UINT, UINT);
LONG DispatchMessageA(const(MSG)*);
LONG DispatchMessageW(const(MSG)*);
BOOL TranslateMessage(const(MSG)*);
HWND CreateWindowExA(int, LPCSTR, LPCSTR, DWORD, int, int, int, int, HWND, HMENU, HINSTANCE, void*);
HWND CreateWindowExW(int, LPCWSTR, LPCWSTR, DWORD, int, int, int, int, HWND, HMENU, HINSTANCE, void*);
HBRUSH GetSysColorBrush(int);
alias LRESULT function(HWND, UINT, WPARAM, LPARAM) WNDPROC;
enum
{
NULL = null,
COLOR_3DFACE = 15,
BS_GROUPBOX = 7,
}
const LPCTSTR IDC_ARROW = cast(LPCTSTR)32512;
struct MSG
{
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
DWORD time;
POINT pt;
}
struct WNDCLASSA
{
UINT style;
WNDPROC lpfnWndProc;
int cbClsExtra;
int cbWndExtra;
HINSTANCE hInstance;
HICON hIcon;
HCURSOR hCursor;
HBRUSH hbrBackground;
LPCSTR lpszMenuName;
LPCSTR lpszClassName;
}
struct WNDCLASSW
{
UINT style;
WNDPROC lpfnWndProc;
int cbClsExtra;
int cbWndExtra;
HINSTANCE hInstance;
HICON hIcon;
HCURSOR hCursor;
HBRUSH hbrBackground;
LPCWSTR lpszMenuName;
LPCWSTR lpszClassName;
}
enum
{
WS_OVERLAPPED = 0,
WS_TILED = WS_OVERLAPPED,
WS_MAXIMIZEBOX = 0x00010000,
WS_MINIMIZEBOX = 0x00020000,
WS_TABSTOP = 0x00010000,
WS_GROUP = 0x00020000,
WS_THICKFRAME = 0x00040000,
WS_SIZEBOX = WS_THICKFRAME,
WS_SYSMENU = 0x00080000,
WS_HSCROLL = 0x00100000,
WS_VSCROLL = 0x00200000,
WS_DLGFRAME = 0x00400000,
WS_BORDER = 0x00800000,
WS_CAPTION = 0x00c00000,
WS_OVERLAPPEDWINDOW = WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX,
WS_TILEDWINDOW = WS_OVERLAPPEDWINDOW,
WS_MAXIMIZE = 0x01000000,
WS_CLIPCHILDREN = 0x02000000,
WS_CLIPSIBLINGS = 0x04000000,
WS_DISABLED = 0x08000000,
WS_VISIBLE = 0x10000000,
WS_MINIMIZE = 0x20000000,
WS_ICONIC = WS_MINIMIZE,
WS_CHILD = 0x40000000,
WS_CHILDWINDOW = 0x40000000,
WS_POPUP = 0x80000000,
WS_POPUPWINDOW = WS_POPUP|WS_BORDER|WS_SYSMENU,
}
pragma(startaddress, mainCRTStartup);
int mainCRTStartup()
{
MSG msg;
HWND hWndParent;
WNDCLASS wndClass =
{
0, &DefWindowProc, 0, 0, NULL, NULL, LoadCursor(NULL, IDC_ARROW),
GetSysColorBrush(COLOR_3DFACE), NULL, "MyClass"
};
ATOM atom = RegisterClass(&wndClass);
hWndParent = CreateWindowEx(
0, wndClass.lpszClassName, NULL, WS_VISIBLE | WS_OVERLAPPEDWINDOW,
0, 0, 33, 100, NULL, NULL, NULL, NULL);
CreateWindowEx(0, "Button", wndClass.lpszClassName,
WS_VISIBLE | WS_CHILD | BS_GROUPBOX,
5, 5, 100, 50, hWndParent, NULL, NULL, NULL);
while (GetMessage(&msg, hWndParent, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
Either I'm doing something wrong, or it's a compiler bug... but even if it's a compiler bug, I still have no idea how something like this can happen, because it would need to call very specific APIs! Ideas?
This is subsystem version issue (linker responsibility). Add -L/SUBSYSTEM:CONSOLE:4.0 to dmd command line to fix MyClass background color. Walter likes old systems so default OPTLINK subsystem version is 3.10. Looks like Microsoft's link 9.0 use 5.0 as default subsystem version.
Linux guy here so I will do my best:
It looks like a problem with the library itself. My guess is you got it from here?
https://github.com/AndrejMitrovic/DWinProgramming
In this case the solution is to contact the fellow who wrote the dmd win32 library you are using. If you compiled them from source then certainly there is a way to contact that person. It appears you have found a bug!
PS: One other possibility if you compiled the libraries from source. You may have a compile argument or flag that is different and causes the difference. Also, perhaps it is a compatibility issue with a library dependency. In this case the answer is still to contact the developer of the library. He will probably ask you for some compile output.

TabControl clips client area when displaying overflow arrows

This bug appears only with common control v6 (theme enabled) on XP (seems to work on 7 and 2008). I wonder if someone else might have seen this bug feature.
When you have a single-line TabControl with lots of tabs, a pairs of arrows should appear if there is not enough space to display all the tabs. This is all nice except that the client area is also clipped, which is not nice at all.
Have I miss something ? I played with tabcontrol's window style, but no luck so far.
To illustrate this, it's actually best to see it in action:
#define UNICODE
#include <windows.h>
#include <commctrl.h>
#include <stdio.h>
LRESULT CALLBACK WindowProcedure(HWND, UINT, WPARAM, LPARAM);
HWND htab, hbut;
int WINAPI WinMain (HINSTANCE instance,
HINSTANCE previnst,
LPSTR args,
int wndState)
{
int i;
MSG messages;
WNDCLASSEX wincl = {
.hInstance = instance, .lpszClassName = L"WindowsApp",
.lpfnWndProc = WindowProcedure, .style = CS_DBLCLKS, .cbSize = sizeof wincl,
.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1)
};
InitCommonControls();
wincl.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor(NULL, IDC_ARROW);
if (!RegisterClassEx (&wincl))
return 0;
HWND hwnd = CreateWindow(L"WindowsApp", L"Windows App", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 544, 375, HWND_DESKTOP, NULL, instance, NULL);
htab = CreateWindowEx(WS_EX_CONTROLPARENT, WC_TABCONTROL,
L"MyTab", WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE, 10, 10, 514, 325, hwnd,
(HMENU) 10, instance, NULL);
hbut = CreateWindow(
WC_BUTTON, L"My nice button that is clipped", WS_CHILD | WS_VISIBLE | WS_TABSTOP,
10, 30, 494, 285, htab, (HMENU) IDOK, instance, NULL
);
for (i = 0; i < 10; i ++)
{
WCHAR myBuf[100];
TCITEM tc = {.mask = TCIF_TEXT, .pszText = myBuf};
wsprintf(myBuf, L"My super tab %d", i + 1);
TabCtrl_InsertItem(htab, i, &tc);
}
SendMessage(hbut, WM_SETFONT, (LPARAM) GetStockObject(DEFAULT_GUI_FONT), FALSE);
SendMessage(htab, WM_SETFONT, (LPARAM) GetStockObject(DEFAULT_GUI_FONT), FALSE);
ShowWindow(hwnd, wndState);
while (GetMessage (&messages, NULL, 0, 0))
{
TranslateMessage(&messages);
DispatchMessage(&messages);
}
return messages.wParam;
}
LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
RECT r;
switch (message) {
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_SIZE:
GetClientRect(hwnd, &r);
MoveWindow(htab, 10, 10, r.right-20, r.bottom - 20, TRUE);
MoveWindow(hbut, 10, 30, r.right-40, r.bottom - 60, TRUE);
break;
case WM_COMMAND:
break;
default:
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}
Unfortunately I can't test it (I have Win7) but according to http://msdn.microsoft.com/en-us/library/hh298367%28v=VS.85%29.aspx you need to have clip siblings on the tab control and also the parent window. You could also try using the tab control's adjust rect message to get the positions for your button.

How do I create a normal win32 edit control?

I'm trying to create an edit control with the regular 3D border around it (in the classic windows style, anyway), but it just has a 1px black border around it. Here is my CreateWindowEx call:
return CreateWindowEx(0, "EDIT", "E:\\bk",
WS_VISIBLE | WS_CHILD | WS_BORDER | ES_LEFT,
87, 81, 150, 17,
main_window.hwnd,
(HMENU)5, hInstance, NULL);
If I exclude WS_BORDER then it's just a white box. Any ideas on what's wrong here?
Update
WS_EX_CLIENTEDGE did the trick.
I don't know anything about manifest files, or how to make the window use the more modern windows themes (XP, for example), instead of the chunky 3D borders. But, when I do learn all that, will WS_EX_CLIENTEDGE make them use those themes instead, or will it enforce the 3D look?
Try using WS_EX_CLIENTEDGE. That will create an inset 3-D window border under typical situations.
return CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "E:\\bk",
WS_VISIBLE | WS_CHILD | WS_BORDER | ES_LEFT,
87, 81, 150, 17,
main_window.hwnd,
(HMENU)5, hInstance, NULL);
Also see the following link for the rest of the available flags for CreateWindowEx.
CreateWindowEx at MSDN
He is right WS_EX_CLIENTEDGE will do the 3D border.
I think you mean the 'WS_EX_DLGMODALFRAME' style. It makes it look like the old-style 3d raised type look. Combined with 'WS_BORDER' to make it look a like a 3d border around the control.
Below code Creates an input box and a button, when clicked updates title.
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int main() {
HINSTANCE hInstance;
MSG msg;
WNDCLASSW wc = {0};
wc.lpszClassName = L"Edit control";
wc.hInstance = hInstance;
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
wc.lpfnWndProc = WndProc;
wc.hCursor = LoadCursor(0, IDC_ARROW);
RegisterClassW(&wc);
CreateWindowW(wc.lpszClassName, L"Edit control",
WS_OVERLAPPEDWINDOW | WS_VISIBLE, 220, 220, 280, 200, 0, 0,
hInstance, 0);
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
static HWND hwndEdit;
HWND hwndButton;
switch (msg) {
case WM_CREATE:
hwndEdit = CreateWindowW(L"Edit", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER,
50, 50, 150, 20, hwnd, (HMENU)102, NULL, NULL);
hwndButton = CreateWindowW(L"button", L"Set title", WS_VISIBLE | WS_CHILD,
50, 100, 80, 25, hwnd, (HMENU)103, NULL, NULL);
break;
case WM_COMMAND:
if (HIWORD(wParam) == BN_CLICKED) {
int len = GetWindowTextLengthW(hwndEdit) + 1;
wchar_t text[len];
GetWindowTextW(hwndEdit, text, len);
SetWindowTextW(hwnd, text);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProcW(hwnd, msg, wParam, lParam);
}
To compile:
g++ test.cpp -o test.exe -mwindows
source: zetcode.com/editcontrol

Resources