Related
I'm trying to implement a text highlighting and undo in RichEdit. The code below marks 5 and 6 chars but undo doesn't work (the text doesn't change) though Edit_CanUndo returns 1. If I turn off a updateHighlighting then undo works but it rolls back too much at once (e.g. input a long text, paste a text by Ctrl+V, input another text - it's required only 3 undo to rollback all).
What is wrong with my code? Maybe I should return a specific value from updateHighlighting?
#define UNICODE
#define _UNICODE
#include <tchar.h>
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <richedit.h>
#define IDC_EDITOR 1000
#define IDC_BUTTON 1001
HWND hEditorWnd;
bool updateHighlighting(HWND hWnd) {
int carriagePos = 0;
SendMessage(hWnd, EM_GETSEL, (WPARAM)&carriagePos, (WPARAM)&carriagePos);
CHARFORMAT cf = {0};
cf.cbSize = sizeof(CHARFORMAT) ;
cf.dwMask = CFM_COLOR | CFM_BOLD;
cf.crTextColor = RGB(0, 0, 200);
cf.dwEffects = CFM_BOLD;
SendMessage(hWnd, EM_SETSEL, 0, -1);
SendMessage(hWnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM) &cf);
cf.dwMask = CFM_COLOR | CFM_BOLD;
cf.dwEffects = cf.dwEffects & ~CFM_BOLD;
cf.crTextColor = RGB(200, 0, 0);
SendMessage(hWnd, EM_SETSEL, 4, 6);
SendMessage(hWnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM) &cf);
SendMessage(hWnd, EM_SETSEL, carriagePos, carriagePos);
_tprintf(TEXT("End highlight\n"));
return true;
}
LRESULT CALLBACK WindowProcedure (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_DESTROY:
PostQuitMessage (0);
break;
case WM_COMMAND: {
if (LOWORD(wParam) == IDC_EDITOR && HIWORD(wParam) == EN_CHANGE)
return updateHighlighting(hEditorWnd);
if (LOWORD(wParam) == IDC_BUTTON && HIWORD(wParam) == BN_CLICKED)
_tprintf(TEXT("UNDO: can %i => result: %i\n"), Edit_CanUndo(hEditorWnd), Edit_Undo(hEditorWnd));
}
break;
default:
return DefWindowProc (hWnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow) {
InitCommonControls();
LoadLibrary(TEXT("msftedit.dll"));
HWND hWnd;
MSG msg;
WNDCLASSEX wincl;
wincl.hInstance = hThisInstance;
wincl.lpszClassName = TEXT("AppClass");
wincl.lpfnWndProc = WindowProcedure;
wincl.style = CS_DBLCLKS;
wincl.cbSize = sizeof (WNDCLASSEX);
wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
wincl.lpszMenuName = NULL;
wincl.cbClsExtra = 0;
wincl.cbWndExtra = 0;
wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
if (!RegisterClassEx (&wincl))
return 0;
hWnd = CreateWindowEx (0, TEXT("AppClass"), TEXT("Test"), WS_OVERLAPPEDWINDOW | WS_VISIBLE, 300, 400, 310, 375, HWND_DESKTOP, NULL, hThisInstance, NULL);
CreateWindowEx(0, WC_BUTTON , L"UNDO", WS_VISIBLE | WS_CHILD | WS_TABSTOP, 10, 310, 280, 30, hWnd, (HMENU)IDC_BUTTON, hThisInstance, NULL);
hEditorWnd = CreateWindowEx(0, TEXT("RICHEDIT50W"), NULL, WS_VISIBLE | WS_CHILD | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP | ES_NOHIDESEL, 0, 0, 300, 300, hWnd, (HMENU)IDC_EDITOR, hThisInstance, NULL);
SendMessage(hEditorWnd, EM_SETEVENTMASK, 0, ENM_CHANGE | ENM_UPDATE | ENM_KEYEVENTS);
while (GetMessage (&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
P.S. I use Code::Block 17.12 + gcc5.1 on Win7x64 (but build a 32bit app).
What you mean exactly with "doesn't work" or with when it "does work" is unclear, however, changing color is something that can be undone too so if you do not want that, then you have to turn off undo before coloring and resume it after coloring.
I don't know if there are easier ways to do it, but in C I use the following functions:
//#include <windows, richedit, ...>
#include <TOM.h>
extern HWND ghEditWnd;
static IUnknown *pUnk;
static ITextDocument *pDoc;
static const IID IID_ITextDocument = {
0x8CC497C0, 0xA1DF, 0x11CE,
{0x80,0x98,0x00,0xAA,0x00,0x47,0xBE,0x5D}
};
static int tomInit(void)
{
if (!pUnk) SendMessage(ghEditWnd, EM_GETOLEINTERFACE, 0, (LPARAM)&pUnk);
if (!pUnk || pUnk->lpVtbl->QueryInterface(pUnk,&IID_ITextDocument, &pDoc) != NOERROR)
{pUnk= 0; return FALSE;}
return TRUE;
}
void undoSuspend(void)
{
if (!pUnk) if (!tomInit()) return;
pDoc->lpVtbl->Undo(pDoc,tomSuspend,0); //Suspends Undo.
}
void undoResume(void)
{
if (!pUnk) if (!tomInit()) return;
pDoc->lpVtbl->Undo(pDoc,tomResume,0); // resume Undo.
}
void releaseTOM(void)
{
if (pUnk) {
pUnk->lpVtbl->Release(pUnk); pUnk= 0; pDoc= 0;
}
}
See also https://learn.microsoft.com/en-us/windows/win32/api/tom/
EDIT: in question How to disable Undo in Rich Text Box in WPF? the suggestion was to set UndoLimit to zero. It is not clear if that would clear the existing undo stack too.
Undo can be suspended and resumed in RichEdit 3.0, Microsoft says.
Here is the working example (undo removes symbols char-by-char as I want) based on Paul Ogilvie's reply and codepilot answer.
Hint: use freeze/unfreeze to prevent flickering. That is similar to SetWindowRedraw(hWnd, TRUE/FALSE) but the last operation arouse unnecessary EN_SELCHANGE notification messages.
#define UNICODE
#define _UNICODE
#include <tchar.h>
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <richedit.h>
// Code::Block doesn't have a tom.h :(
// https://github.com/kinke/mingw-w64-crt/blob/master/mingw-w64-headers/include/tom.h
#include "tom.h"
#include <richole.h>
#include <unknwn.h>
IUnknown *tr_code = NULL;
ITextDocument *td_code;
#define DEFINE_GUIDXXX(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) EXTERN_C const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
DEFINE_GUIDXXX(IID_ITextDocument,0x8CC497C0,0xA1DF,0x11CE,0x80,0x98, 0x00,0xAA,0x00,0x47,0xBE,0x5D);
#define IDC_EDITOR 1000
#define IDC_BUTTON 1001
HWND hEditorWnd;
bool updateHighlighting(HWND hWnd) {
int carriagePos = 0;
SendMessage(hWnd, EM_GETSEL, (WPARAM)&carriagePos, (WPARAM)&carriagePos);
CHARFORMAT cf = {0};
cf.cbSize = sizeof(CHARFORMAT) ;
cf.dwMask = CFM_COLOR | CFM_BOLD;
cf.crTextColor = RGB(0, 0, 200);
cf.dwEffects = CFM_BOLD;
SendMessage(hWnd, EM_SETSEL, 0, -1);
SendMessage(hWnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM) &cf);
cf.dwMask = CFM_COLOR | CFM_BOLD;
cf.dwEffects = cf.dwEffects & ~CFM_BOLD;
cf.crTextColor = RGB(200, 0, 0);
SendMessage(hWnd, EM_SETSEL, 4, 6);
SendMessage(hWnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM) &cf);
SendMessage(hWnd, EM_SETSEL, carriagePos, carriagePos);
_tprintf(TEXT("End highlight\n"));
return true;
}
LRESULT CALLBACK WindowProcedure (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_DESTROY:
PostQuitMessage (0);
break;
case WM_COMMAND: {
if (LOWORD(wParam) == IDC_BUTTON && HIWORD(wParam) == BN_CLICKED)
_tprintf(TEXT("UNDO: can %i => result: %i\n"), Edit_CanUndo(hEditorWnd), Edit_Undo(hEditorWnd));
if (LOWORD(wParam) == IDC_EDITOR && HIWORD(wParam) == EN_CHANGE) {
long cnt = 0;
td_code->Undo(tomSuspend, NULL); // <---
td_code->Freeze(&cnt); // <---
updateHighlighting(hEditorWnd);
td_code->Unfreeze(&cnt); // <---
td_code->Undo(tomResume, NULL); // <---
return 1;
}
}
break;
default:
return DefWindowProc (hWnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow) {
InitCommonControls();
LoadLibrary(TEXT("msftedit.dll"));
HWND hWnd;
MSG msg;
WNDCLASSEX wincl;
wincl.hInstance = hThisInstance;
wincl.lpszClassName = TEXT("AppClass");
wincl.lpfnWndProc = WindowProcedure;
wincl.style = CS_DBLCLKS;
wincl.cbSize = sizeof (WNDCLASSEX);
wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
wincl.lpszMenuName = NULL;
wincl.cbClsExtra = 0;
wincl.cbWndExtra = 0;
wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
if (!RegisterClassEx (&wincl))
return 0;
hWnd = CreateWindowEx (0, TEXT("AppClass"), TEXT("Test"), WS_OVERLAPPEDWINDOW | WS_VISIBLE, 300, 400, 310, 375, HWND_DESKTOP, NULL, hThisInstance, NULL);
CreateWindowEx(0, WC_BUTTON , L"UNDO", WS_VISIBLE | WS_CHILD | WS_TABSTOP, 10, 310, 280, 30, hWnd, (HMENU)IDC_BUTTON, hThisInstance, NULL);
hEditorWnd = CreateWindowEx(0, TEXT("RICHEDIT50W"), NULL, WS_VISIBLE | WS_CHILD | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP | ES_NOHIDESEL, 0, 0, 300, 300, hWnd, (HMENU)IDC_EDITOR, hThisInstance, NULL);
SendMessage(hEditorWnd, EM_SETEVENTMASK, 0, ENM_CHANGE | ENM_UPDATE | ENM_KEYEVENTS);
// \/
SendMessage(hEditorWnd, EM_GETOLEINTERFACE, 0, (LPARAM)&tr_code);
if(tr_code == (IRichEditOle*)NULL) {
MessageBox(0, TEXT("Error when trying to get RichEdit OLE Object"), NULL, 0);
return 0;
}
tr_code->QueryInterface(IID_ITextDocument,(void**)&td_code);
// /\
while (GetMessage (&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
I am trying to create a dialog box and it returns an error in the resource file. I have been trying to execute different types of codes and ever found the issue. It says unknown type IDD_TOOL. What is it that's wrong here?
The errors that I get is:
[Error] unknown type name 'IDD_TOOLBAR'
[Error] expected '=', ',', ';', 'asm' or '__attribute__' before numeric constant (line 2 column 22 for resource code.)
This is the resource code.
IDD_ABOUT DIALOG DISCARDABLE 0, 0, 239, 66
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "My About Box"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "&OK",IDOK,174,18,50,14
PUSHBUTTON "&Cancel",IDCANCEL,174,35,50,14
GROUPBOX "About this program...",IDC_STATIC,7,7,225,52
CTEXT "An example program showing how to use Dialog Boxes\r\n\r\nby theForger",
IDC_STATIC,16,18,144,33
END
This is the main code.
#include<windows.h>
#include "new.rc"
#include "main.h"
#define THEICON "windowIco.ico"
HWND g_hToolbar;
LRESULT CALLBACK newStartCallback(HWND newWindow, UINT msg, WPARAM wparam, LPARAM lparam){
HMENU hmenu, hsubmenu;
switch(msg){
case WM_CREATE:
hmenu= CreateMenu();
hsubmenu = CreatePopupMenu();
AppendMenu(hsubmenu, MF_STRING|MF_POPUP, 10001 , "&New");
AppendMenu(hsubmenu, MF_STRING|MF_POPUP, 10002, "&Save File");
AppendMenu(hmenu, MF_STRING|MF_POPUP, (UINT)hsubmenu, "&File");
hsubmenu = CreatePopupMenu();
AppendMenu(hsubmenu, MF_STRING|MF_POPUP, 10003, "&Start");
AppendMenu(hsubmenu, MF_STRING|MF_POPUP, 10004, "&dialogbox...");
AppendMenu(hmenu, MF_STRING|MF_POPUP, (UINT)hsubmenu, "&uyu");
SetMenu(newWindow, hmenu); //Forgot to add Set Menu function here
break;
case WM_COMMAND:
switch(LOWORD(wparam)){ //gets low order of wparam.... LOWORD FUNCTION ONE PARAMETER INSIDE GETS ITS LOW ORDER VALUE
case 10003:
printf(" asdaksda");
break;
case 1004:
// int dialogBoxint = DialogBox(GetModuleHandle(NULL), , newWindow, );
break;
default:
printf(" asda");
break;
}
break;
default:
return DefWindowProc(newWindow, msg, wparam, lparam);
}
}
char classNameofTheNewWnd[] = "StartNewClass";
int WINAPI WinMain(HINSTANCE newWindowIns, HINSTANCE newPREVwindowIns, LPSTR dontknowthis, int nCommandShow){
HWND newWindow;
WNDCLASSEX windowclass;
windowclass.cbSize = sizeof(WNDCLASSEX);
windowclass.style = 0;
windowclass.lpfnWndProc = newStartCallback;
windowclass.hIcon = LoadImage(GetModuleHandle(NULL), THEICON, IMAGE_ICON, LR_DEFAULTSIZE, LR_DEFAULTSIZE, LR_LOADFROMFILE); //
windowclass.hIconSm = LoadIcon(GetModuleHandle(NULL), THEICON); //turned to GetModuleHandle(NULL) from plain NULL // THESE ARE THE ICONS LETS SEE WHICH ONE WORKS NOW :))))
windowclass.lpszMenuName = NULL;
windowclass.lpszClassName = classNameofTheNewWnd;
windowclass.hbrBackground = (HBRUSH)(COLOR_WINDOW-2);
windowclass.cbWndExtra = 0;
windowclass.cbClsExtra = 0;
windowclass.hInstance = newWindowIns;
windowclass.hCursor = LoadCursor(NULL, IDC_CROSS);
if(!RegisterClassEx(&windowclass)){
printf("no");
}
newWindow = CreateWindowEx(WS_EX_CLIENTEDGE, classNameofTheNewWnd, "Start Something New", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 1200, 550, NULL, NULL, newWindowIns, NULL);
ShowWindow(newWindow, nCommandShow);
MSG message;
while(GetMessage(&message, NULL, 0, 0) > 0){ //don't forget to compare here..... if it is more than 0 then it means there is a new message!!!! :D
TranslateMessage(&message);
DispatchMessage(&message);
}
printf("message.wParam");
return message.wParam;
}
I have been working on a tab controlled program for awhile now and have only recently been posting on StackOverflow for help. Currently the program runs as follows:
Begin in winMain, Creation of main_hwnd generates WM_CREATE and wndProc is called
tab_hwnd is created as a SysTabControl32
tab0_hwnd, tab1_hwnd, ..., tab4_hwnd are created
In tab0_hwnd, static text and buttons are created
Return to winMain and ShowWindow() is called on main_hwnd, tab_hwnd and tab0_hwnd
Enter a loop until program is closed.
When the program is run, everything is visible; however, the buttons do not function properly. At the same time, when I was searching for errors using GetLastError() and FormatMessage() I found that after creating windows tab#_hwnd (where # = 0,1,2,3 and 4), the following error appears:
Error 6: The handle is Invalid
I am not sure as to why this error appears and why the button does not work. Another user has suggested the following in a previous post:
"WM_COMMAND is sent to immediate parent window, not to grandparents, so you'll either have to subclass your tab controls too, or make your buttons have your main window as parent." - Anton Kovalenko
Edit 1: I am unsure how to subclass my tab controls as suggested by Anton Kovalenko. Any links to tutorials/explanations to comments would be extremely helpful.
Here is the current code:
#define WIN32_LEAN_AND_MEAN
#pragma comment(lib, "comctl32.lib")
#define ID_FILE_EXIT 101
#define ID_HELP_ABOUT 102
#define ID_B_BLANK 1001
#define ID_B_HOME 1002
#define ID_B_SAVE 1003
#include <strsafe.h>
#include <windows.h>
#include <CommCtrl.h>
#include <iostream>
#include <ShlObj.h>
HWND main_hwnd, tab_hwnd, tab0_hwnd, tab1_hwnd, tab2_hwnd, tab3_hwnd, tab4_hwnd;
HINSTANCE tab_hinst;
TCHAR HomePath[MAX_PATH*2], SavePath[MAX_PATH*2];
WNDCLASSEX wc;
bool success=FALSE;
MSG msg;
HWND button;
static HWND text;
TCITEM tie;
int focus = 0, NotifyCase = 0;
void ErrorExit(LPTSTR lpszFunction)
{
// Retrieve the system error message for the last-error code
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
// Display the error message and exit the process
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
(lstrlen((LPCTSTR)lpMsgBuf)+lstrlen((LPCTSTR)lpszFunction)+40)*sizeof(TCHAR));
StringCchPrintf((LPTSTR)lpDisplayBuf,
LocalSize(lpDisplayBuf) / sizeof(TCHAR),
TEXT("%s failed with error %d: %s"),
lpszFunction, dw, lpMsgBuf);
MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
ExitProcess(dw);
}
// Call with ErrorExit(TEXT("ANYTHINGHERE"));
LRESULT CALLBACK WndProc(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
switch(Msg)
{
case WM_CREATE:
{
tab_hwnd = CreateWindowEx(
0,
"SysTabControl32",
"",
WS_CHILD,
CW_USEDEFAULT, CW_USEDEFAULT, 681, 338,
hwnd, NULL, tab_hinst, NULL);
tab0_hwnd = CreateWindowEx(
0,
"SysTabControl32",
"",
WS_CHILD,
1, 22, 679, 315,
tab_hwnd, NULL, tab_hinst, NULL);
//ErrorExit(TEXT("HERE")); //<--- This gives error 6: Handle invalid
text = CreateWindow("Static","Home Directory",WS_CHILD | WS_VISIBLE,0,50,150,50,tab0_hwnd, 0, tab_hinst,0);
text = CreateWindow("Static","C:\\",WS_CHILD | WS_VISIBLE,200,50,150,50,tab0_hwnd, 0, tab_hinst,0);
button = CreateWindow("Button","Navigate to...", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE ,350,42,100,25,tab0_hwnd,(HMENU)ID_B_HOME,tab_hinst,0);
text = CreateWindow("Static","Save Directory",WS_CHILD | WS_VISIBLE,0,100,150,50,tab0_hwnd, 0, tab_hinst,0);
text = CreateWindow("Static","C:\\",WS_CHILD | WS_VISIBLE,200,100,150,50,tab0_hwnd, 0, tab_hinst,0);
button = CreateWindow("Button","Save to...", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE ,350,92,100,25,tab0_hwnd,(HMENU)ID_B_SAVE,tab_hinst,0);
tab1_hwnd = CreateWindowEx(
0,
"SysTabControl32",
"",
WS_CHILD,
1, 22, 679, 315,
tab_hwnd, NULL, tab_hinst, NULL);
tab2_hwnd = CreateWindowEx(
0,
"SysTabControl32",
"",
WS_CHILD,
1, 22, 679, 315,
tab_hwnd, NULL, tab_hinst, NULL);
tab3_hwnd = CreateWindowEx(
0,
"SysTabControl32",
"",
WS_CHILD,
1, 22, 679, 315,
tab_hwnd, NULL, tab_hinst, NULL);
tab4_hwnd = CreateWindowEx(
0,
"SysTabControl32",
"",
WS_CHILD,
1, 22, 679, 315,
tab_hwnd, NULL, tab_hinst, NULL);
tie.mask = TCIF_TEXT;
tie.pszText = "Paths";
TabCtrl_InsertItem(tab_hwnd, 0, &tie);
tie.pszText = "Output";
TabCtrl_InsertItem(tab_hwnd, 1, &tie);
tie.pszText = "Parameters";
TabCtrl_InsertItem(tab_hwnd, 2, &tie);
tie.pszText = "Configurations";
TabCtrl_InsertItem(tab_hwnd, 3, &tie);
tie.pszText = "Run";
TabCtrl_InsertItem(tab_hwnd, 4, &tie);
HMENU hMenu, hSubMenu;
hMenu = CreateMenu();
hSubMenu = CreatePopupMenu();
AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "&File");
AppendMenu(hSubMenu, MF_STRING, ID_FILE_EXIT, "&Exit");
hSubMenu = CreatePopupMenu();
AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "&Help");
AppendMenu(hSubMenu, MF_STRING, ID_HELP_ABOUT, "&About");
SetMenu(hwnd, hMenu);
}
break;
case WM_NOTIFY:
switch(((LPNMHDR)lParam) ->code)
{
case TCN_SELCHANGING:
switch(TabCtrl_GetCurFocus(tab_hwnd))
{
case 0:
ShowWindow(tab0_hwnd,SW_HIDE);
break;
case 1:
ShowWindow(tab1_hwnd,SW_HIDE);
break;
case 2:
ShowWindow(tab2_hwnd,SW_HIDE);
break;
case 3:
ShowWindow(tab3_hwnd,SW_HIDE);
break;
case 4:
ShowWindow(tab4_hwnd,SW_HIDE);
break;
default:
return DefWindowProc(hwnd, Msg, wParam, lParam);
break;
}
break;
case TCN_SELCHANGE:
switch(TabCtrl_GetCurFocus(tab_hwnd))
{
case 0:
ShowWindow(tab0_hwnd,SW_SHOW);
break;
case 1:
ShowWindow(tab1_hwnd,SW_SHOW);
break;
case 2:
ShowWindow(tab2_hwnd,SW_SHOW);
break;
case 3:
ShowWindow(tab3_hwnd,SW_SHOW);
break;
case 4:
ShowWindow(tab4_hwnd,SW_SHOW);
break;
default:
return DefWindowProc(hwnd, Msg, wParam, lParam);
break;
}
break;
default:
return DefWindowProc(hwnd, Msg, wParam, lParam);
}
break;
case WM_COMMAND:
//MessageBox(tab0_hwnd,"HERE","OKAY",NULL);
switch(LOWORD(wParam))
{
case ID_FILE_EXIT:
PostMessage(hwnd, WM_CLOSE, 0, 0);
break;
case ID_HELP_ABOUT:
return MessageBox(0, "This program is an alteration of ...", "About", MB_OK);
case ID_B_HOME:
if(BN_CLICKED == HIWORD(wParam)){
MessageBox(tab0_hwnd,"HERE","OKAY",NULL);
}
break;
case ID_B_SAVE:
if(BN_CLICKED == HIWORD(wParam)){
}
break;
case ID_B_BLANK:
break;
default:
return DefWindowProc(hwnd, Msg, wParam, lParam);
}
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)
{
InitCommonControls();
tab_hinst = hInstance;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
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 = "Home";
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if(!RegisterClassEx(&wc))
MessageBox(NULL, "Window Registration Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);
main_hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
"Home",
"The Home page",
WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
CW_USEDEFAULT, CW_USEDEFAULT, 700, 400,
NULL, NULL, hInstance, NULL);
if(main_hwnd == NULL) {
MessageBox(NULL, "Window Creation Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(main_hwnd, nCmdShow);
ShowWindow(tab_hwnd,SW_SHOW);
ShowWindow(tab0_hwnd,SW_SHOW);
UpdateWindow(main_hwnd);
do{
PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE);
TranslateMessage(&msg);
DispatchMessage(&msg);
} while(msg.message!=WM_CLOSE && msg.message!=WM_QUIT);
return msg.wParam;
}
I have been working on a Tab Control and it is only visible when posted in winMain. When I try creating the tabs in the WM_CREATE message handle, nothing shows up. Here is my code:
#define WIN32_LEAN_AND_MEAN
#define IDC_STATIC -1
#define ID_FILE_EXIT 101
#define ID_HELP_ABOUT 102
#define ID_B_BLANK 1001
#define ID_B_HOME 1002
#define ID_B_SAVE 1003
#include <strsafe.h>
#include <windows.h>
#include <CommCtrl.h>
#include <iostream>
#include <ShlObj.h>
#include <cstring>
HWND main_hwnd, tab_hwnd, tab0_hwnd, tab1_hwnd, tab2_hwnd, tab3_hwnd, tab4_hwnd;
HINSTANCE tab_hinst;
TCHAR HomePath[MAX_PATH*2], SavePath[MAX_PATH*2];
WNDCLASSEX wc;
bool success=FALSE;
MSG msg;
HWND button; //button1, button2;
static HWND text; // text1, text2, text3, text4;
TCITEM tie;
int focus = 0, NotifyCase = 0;
void ErrorExit(LPTSTR lpszFunction)
{
// Retrieve the system error message for the last-error code
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
// Display the error message and exit the process
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
(lstrlen((LPCTSTR)lpMsgBuf)+lstrlen((LPCTSTR)lpszFunction)+40)*sizeof(TCHAR));
StringCchPrintf((LPTSTR)lpDisplayBuf,
LocalSize(lpDisplayBuf) / sizeof(TCHAR),
TEXT("%s failed with error %d: %s"),
lpszFunction, dw, lpMsgBuf);
MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
ExitProcess(dw);
}
// Step 4: The Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
switch(Msg)
{
case WM_CREATE:
{
tab_hwnd = CreateWindowEx(
0,
"SysTabControl32",
"",
WS_CHILD|WS_CLIPSIBLINGS,
CW_USEDEFAULT, CW_USEDEFAULT, 681, 338,
main_hwnd, NULL, tab_hinst, NULL);
tab0_hwnd = CreateWindowEx(
0,
"SysTabControl32",
"",
WS_CHILD|WS_CLIPSIBLINGS,
1, 22, 679, 315,
tab_hwnd, NULL, tab_hinst, NULL);
text = CreateWindow("Static","Home Directory",WS_CHILD | WS_VISIBLE,0,50,150,50,tab0_hwnd, 0, tab_hinst,0);
text = CreateWindow("Static","C:\\",WS_CHILD | WS_VISIBLE,200,50,150,50,tab0_hwnd, 0, tab_hinst,0);
button = CreateWindow("Button","Navigate to...", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE ,350,42,100,25,tab0_hwnd,(HMENU)ID_B_HOME,tab_hinst,0);
text = CreateWindow("Static","Save Directory",WS_CHILD | WS_VISIBLE,0,100,150,50,tab0_hwnd, 0, tab_hinst,0);
text = CreateWindow("Static","C:\\",WS_CHILD | WS_VISIBLE,200,100,150,50,tab0_hwnd, 0, tab_hinst,0);
button = CreateWindow("Button","Save to...", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE ,350,92,100,25,tab0_hwnd,(HMENU)ID_B_SAVE,tab_hinst,0);
tab1_hwnd = CreateWindowEx(
0,
"SysTabControl32",
"",
WS_CHILD|WS_CLIPSIBLINGS,
1, 22, 679, 315,
tab_hwnd, NULL, tab_hinst, NULL);
tab2_hwnd = CreateWindowEx(
0,
"SysTabControl32",
"",
WS_CHILD|WS_CLIPSIBLINGS,
1, 22, 679, 315,
tab_hwnd, NULL, tab_hinst, NULL);
tab3_hwnd = CreateWindowEx(
0,
"SysTabControl32",
"",
WS_CHILD|WS_CLIPSIBLINGS,
1, 22, 679, 315,
tab_hwnd, NULL, tab_hinst, NULL);
tab4_hwnd = CreateWindowEx(
0,
"SysTabControl32",
"",
WS_CHILD|WS_CLIPSIBLINGS,
1, 22, 679, 315,
tab_hwnd, NULL, tab_hinst, NULL);
tie.mask = TCIF_TEXT;
tie.pszText = "Paths";
TabCtrl_InsertItem(tab_hwnd, 0, &tie);
tie.pszText = "Output";
TabCtrl_InsertItem(tab_hwnd, 1, &tie);
tie.pszText = "Parameters";
TabCtrl_InsertItem(tab_hwnd, 2, &tie);
tie.pszText = "Configurations";
TabCtrl_InsertItem(tab_hwnd, 3, &tie);
tie.pszText = "Run";
TabCtrl_InsertItem(tab_hwnd, 4, &tie);
HMENU hMenu, hSubMenu;
hMenu = CreateMenu();
hSubMenu = CreatePopupMenu();
AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "&File");
AppendMenu(hSubMenu, MF_STRING, ID_FILE_EXIT, "&Exit");
hSubMenu = CreatePopupMenu();
AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "&Help");
AppendMenu(hSubMenu, MF_STRING, ID_HELP_ABOUT, "&About");
SetMenu(hwnd, hMenu);
}
break;
case WM_NOTIFY:
switch(((LPNMHDR)lParam) ->code)
{
case TCN_SELCHANGING:
switch(TabCtrl_GetCurFocus(tab_hwnd))
{
case 0:
ShowWindow(tab0_hwnd,SW_HIDE);
break;
case 1:
ShowWindow(tab1_hwnd,SW_HIDE);
break;
case 2:
ShowWindow(tab2_hwnd,SW_HIDE);
break;
case 3:
ShowWindow(tab3_hwnd,SW_HIDE);
break;
case 4:
ShowWindow(tab4_hwnd,SW_HIDE);
break;
default:
return DefWindowProc(hwnd, Msg, wParam, lParam);
break;
}
break;
case TCN_SELCHANGE:
switch(TabCtrl_GetCurFocus(tab_hwnd))
{
case 0:
ShowWindow(tab0_hwnd,SW_SHOW);
break;
case 1:
ShowWindow(tab1_hwnd,SW_SHOW);
break;
case 2:
ShowWindow(tab2_hwnd,SW_SHOW);
break;
case 3:
ShowWindow(tab3_hwnd,SW_SHOW);
break;
case 4:
ShowWindow(tab4_hwnd,SW_SHOW);
break;
default:
return DefWindowProc(hwnd, Msg, wParam, lParam);
break;
}
break;
default:
return DefWindowProc(hwnd, Msg, wParam, lParam);
}
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case ID_FILE_EXIT:
PostMessage(hwnd, WM_CLOSE, 0, 0);
break;
case ID_HELP_ABOUT:
return MessageBox(0, "This program is an alteration of ...", "About", MB_OK);
//return DefWindowProc(hwnd2,0,0,0);
case ID_B_HOME:
MessageBox(tab0_hwnd,"HERE","OKAY",NULL);
break;
case ID_B_SAVE:
break;
case ID_B_BLANK:
break;
default:
return DefWindowProc(hwnd, Msg, wParam, lParam);
}
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)
{
tab_hinst = hInstance;
//Step 1: Registering the Window Class
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
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 = "Home";
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if(!RegisterClassEx(&wc))
MessageBox(NULL, "Window Registration Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);
// Step 2: Creating the Window
main_hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
"Home",
"The Home page",
WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
CW_USEDEFAULT, CW_USEDEFAULT, 700, 400,
NULL, NULL, hInstance, NULL);
if(main_hwnd == NULL) {
MessageBox(NULL, "Window Creation Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(main_hwnd, nCmdShow);
ShowWindow(tab_hwnd, SW_SHOW);
ShowWindow(tab0_hwnd, SW_SHOW);
UpdateWindow(main_hwnd);
// Step 3: The Message Loop
do{
PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE);
/* Translate virtual-key messages into character messages */
TranslateMessage(&msg);
/* Send message to WindowProcedure */
DispatchMessage(&msg);
} while(msg.message!=WM_CLOSE && msg.message!=WM_QUIT);
return msg.wParam;
}
I believe the process that the code should be following is as follows:
1. Create the main window main_hwnd
2. Goes to WM_CREATE and runs this code
3. During this it creates tab_hwnd, tab0_hwnd, ..., tab4_hwnd
4. Then it returns to winMain, and shows the windows. Afterwards it reaches the loop.
Your main_hwnd is assigned after CreateWindowEx returns, hence it's always NULL when WM_CREATE is delivered. You can use the hwnd parameter of your WndProc instead of main_hwnd.
With this modification, it works for me if I also add InitCommonControls() to the beginning of WinMain (linking against comctl32 library).
I have used GetLastError() and FormatMessage() to determine that the button is successfully being created. However, it is not visible when I run the program. I originally had buttons created in winMain, but found posts online stating NOT to do this, so I commented it out and added the creations in WM_CREATE. Note, all ID's, etc are defined in a resource.h file, and void ErrorExit() was taken from MSDN to make using GetLastError() and FormatMessage() easy on a relatively new winApi programmer like me. My code is as follows:
#define WIN32_LEAN_AND_MEAN
#define _WIN32_IE 0x0900
#define _WIN32_WINNT 0x0900
#include <strsafe.h>
#include <windows.h>
#include <CommCtrl.h>
#include <iostream>
#include <ShlObj.h>
#include <cstring>
#include "resource.h"
HWND main_hwnd, tab_hwnd, tab0_hwnd, tab1_hwnd, tab2_hwnd, tab3_hwnd, tab4_hwnd;
HINSTANCE tab_hinst;
TCHAR HomePath[MAX_PATH*2], SavePath[MAX_PATH*2];
WNDCLASSEX wc;
bool success=FALSE;
MSG msg;
HWND button;
static HWND text;
TCITEM tie;
int focus = 0, NotifyCase = 0;
void ErrorExit(LPTSTR lpszFunction)
{
// Retrieve the system error message for the last-error code
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
// Display the error message and exit the process
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
(lstrlen((LPCTSTR)lpMsgBuf)+lstrlen((LPCTSTR)lpszFunction)+40)*sizeof(TCHAR));
StringCchPrintf((LPTSTR)lpDisplayBuf,
LocalSize(lpDisplayBuf) / sizeof(TCHAR),
TEXT("%s failed with error %d: %s"),
lpszFunction, dw, lpMsgBuf);
MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
ExitProcess(dw);
}
// Step 4: The Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
switch(Msg)
{
case WM_CREATE:
{
if(tab0_hwnd!=NULL)
button = CreateWindow("Button","Navigate to...", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE ,350,42,100,25,tab0_hwnd,(HMENU)ID_B_HOME,(HINSTANCE)GetWindowLong(tab0_hwnd, GWL_HINSTANCE),0);
/*if(tab0_hwnd!=NULL)
button = CreateWindow("Button","Save to...", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE ,350,92,100,25,tab0_hwnd,(HMENU)ID_B_SAVE,(HINSTANCE)GetWindowLong(tab0_hwnd, GWL_HINSTANCE), NULL);
*/HMENU hMenu, hSubMenu;
hMenu = CreateMenu();
hSubMenu = CreatePopupMenu();
AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "&File");
AppendMenu(hSubMenu, MF_STRING, ID_FILE_EXIT, "&Exit");
hSubMenu = CreatePopupMenu();
AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "&Help");
AppendMenu(hSubMenu, MF_STRING, ID_HELP_ABOUT, "&About");
SetMenu(hwnd, hMenu);
}
break;
case WM_NOTIFY:
switch(((LPNMHDR)lParam) ->code)
{
case TCN_SELCHANGING:
switch(TabCtrl_GetCurFocus(tab_hwnd))
{
case 0:
ShowWindow(tab0_hwnd,SW_HIDE);
break;
case 1:
ShowWindow(tab1_hwnd,SW_HIDE);
break;
case 2:
ShowWindow(tab2_hwnd,SW_HIDE);
break;
case 3:
ShowWindow(tab3_hwnd,SW_HIDE);
break;
case 4:
ShowWindow(tab4_hwnd,SW_HIDE);
break;
default:
return DefWindowProc(hwnd, Msg, wParam, lParam);
break;
}
break;
case TCN_SELCHANGE:
switch(TabCtrl_GetCurFocus(tab_hwnd))
{
case 0:
ShowWindow(tab0_hwnd,SW_SHOW);
break;
case 1:
ShowWindow(tab1_hwnd,SW_SHOW);
break;
case 2:
ShowWindow(tab2_hwnd,SW_SHOW);
break;
case 3:
ShowWindow(tab3_hwnd,SW_SHOW);
break;
case 4:
ShowWindow(tab4_hwnd,SW_SHOW);
break;
default:
return DefWindowProc(hwnd, Msg, wParam, lParam);
break;
}
break;
default:
return DefWindowProc(hwnd, Msg, wParam, lParam);
}
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case ID_FILE_EXIT:
PostMessage(hwnd, WM_CLOSE, 0, 0);
break;
case ID_HELP_ABOUT:
return MessageBox(0, "This program is an alteration of...", "About", MB_OK);
//return DefWindowProc(hwnd2,0,0,0);
case ID_B_HOME:
MessageBox(tab0_hwnd,"HERE","OKAY",NULL);
break;
case ID_B_SAVE:
break;
case ID_B_BLANK:
break;
default:
return DefWindowProc(hwnd, Msg, wParam, lParam);
}
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)
{
tab_hinst = hInstance;
//Step 1: Registering the Window Class
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
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 = "Home";
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if(!RegisterClassEx(&wc))
MessageBox(NULL, "Window Registration Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);
// Step 2: Creating the Window
main_hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
"Home",
"The Home page",
WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
CW_USEDEFAULT, CW_USEDEFAULT, 700, 400,
NULL, NULL, hInstance, NULL);
tab_hwnd = CreateWindowEx(
0,
"SysTabControl32",
"",
WS_CHILD|WS_CLIPSIBLINGS,
CW_USEDEFAULT, CW_USEDEFAULT, 681, 338,
main_hwnd, NULL, tab_hinst, NULL);
tab0_hwnd = CreateWindowEx(
0,
"SysTabControl32",
"",
WS_CHILD|WS_CLIPSIBLINGS,
1, 22, 679, 315,
tab_hwnd, NULL, tab_hinst, NULL);
text = CreateWindow("Static","Home Directory",WS_CHILD | WS_VISIBLE,0,50,150,50,tab0_hwnd, 0, tab_hinst,0);
text = CreateWindow("Static","C:\\",WS_CHILD | WS_VISIBLE,200,50,150,50,tab0_hwnd, 0, tab_hinst,0);
//button = CreateWindow("Button","Navigate to...", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE ,350,42,100,25,tab0_hwnd,(HMENU)ID_B_HOME,tab_hinst,0);
text = CreateWindow("Static","Save Directory",WS_CHILD | WS_VISIBLE,0,100,150,50,tab0_hwnd, 0, tab_hinst,0);
text = CreateWindow("Static","C:\\",WS_CHILD | WS_VISIBLE,200,100,150,50,tab0_hwnd, 0, tab_hinst,0);
//button = CreateWindow("Button","Save to...", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE ,350,92,100,25,tab0_hwnd,(HMENU)ID_B_SAVE,tab_hinst,0);
tab1_hwnd = CreateWindowEx(
0,
"SysTabControl32",
"",
WS_CHILD|WS_CLIPSIBLINGS,
1, 22, 679, 315,
tab_hwnd, NULL, tab_hinst, NULL);
tab2_hwnd = CreateWindowEx(
0,
"SysTabControl32",
"",
WS_CHILD|WS_CLIPSIBLINGS,
1, 22, 679, 315,
tab_hwnd, NULL, tab_hinst, NULL);
tab3_hwnd = CreateWindowEx(
0,
"SysTabControl32",
"",
WS_CHILD|WS_CLIPSIBLINGS,
1, 22, 679, 315,
tab_hwnd, NULL, tab_hinst, NULL);
tab4_hwnd = CreateWindowEx(
0,
"SysTabControl32",
"",
WS_CHILD|WS_CLIPSIBLINGS,
1, 22, 679, 315,
tab_hwnd, NULL, tab_hinst, NULL);
tie.mask = TCIF_TEXT;
tie.pszText = "Paths";
TabCtrl_InsertItem(tab_hwnd, 0, &tie);
tie.pszText = "Output";
TabCtrl_InsertItem(tab_hwnd, 1, &tie);
tie.pszText = "Parameters";
TabCtrl_InsertItem(tab_hwnd, 2, &tie);
tie.pszText = "Configurations";
TabCtrl_InsertItem(tab_hwnd, 3, &tie);
tie.pszText = "Run";
TabCtrl_InsertItem(tab_hwnd, 4, &tie);
if(main_hwnd == NULL) {
MessageBox(NULL, "Window Creation Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(main_hwnd, nCmdShow);
ShowWindow(tab_hwnd, nCmdShow);
ShowWindow(tab0_hwnd,nCmdShow);
UpdateWindow(main_hwnd);
UpdateWindow(tab_hwnd);
UpdateWindow(tab0_hwnd);
// Step 3: The Message Loop
do{
PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE);
/* Translate virtual-key messages into character messages */
TranslateMessage(&msg);
/* Send message to WindowProcedure */
DispatchMessage(&msg);
} while(msg.message!=WM_CLOSE && msg.message!=WM_QUIT);
return msg.wParam;
}
Also I'm curious about UpdateWindow(), do I need to call this if I'm not painting?
At WM_CREATE description we read that the message is sent before the function returns.
Hence WM_CREATE for main_hwnd always happens before tab0_hwnd is assigned.
Now let's look at your code handling WM_CREATE:
if(tab0_hwnd!=NULL)
/* you would create the button here, but it does not happen. */
Now, wouldn't it be better to produce an error message if tab0_hwnd is NULL, instead of silently ignoring the error?
It's not necessarily the only problem with the code, but I won't go further without a compilable example.
The call to create the button in the WM_CREATE case of WndProc runs before the the tab0_hwnd window is created. CreateWindow will not return until it calls the WndProc for the window class with WM_CREATE so the order of your code is this:
Create the main window: main_hwnd
Run the code in the WM_CREATE case of WndProc
Create the tab control tab_hwnd
Create the tab control tab0_hwnd
So you need to re-order you code so the button will not be created until after the tab has been created.
Maybe you are missingWS_VISIBLE? It is required or you won't see it.