Preferences Dialog with TreeView and Panel Memory Dialog - c

I have a options dialogbox with a TreeView and different panel beside that i changed when i select tree item.
My first problem is when the options dialog load the focus is set to the default button even if i remove it.
I want to set focus on the first item in the treeview and keep the focus on.
I tried to set the default id:
SendMessage(hDlgOptions, DM_SETDEFID, IDC_TREE, 0);
I tried to set the focus with the NEXTDLGCTL with no success:
SendMessage(hDlgOptions, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hDlgOptions, IDC_TREE), TRUE);
My second problem is the animation of window when the options dialog show up the panel is alredy loaded. I want to load it after th animation show.
I set a timer for the moment... Maybe u have a better solution?
Thanks a lot for your expert review i'll take all good ideas for optimising my code too.
Dialog Load
What i want
resource.rc
IDD_DIALOG_OPTIONS DIALOGEX 0, 0, 395, 175
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Options"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
PUSHBUTTON "OK",ID_BUTTON_SAVE,338,154,50,14
CONTROL "Save config to ini file",IDC_CHECK_SAVE_CONFIG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,252,156,82,10
CONTROL "",IDC_TREE,"SysTreeView32",TVS_DISABLEDRAGDROP | TVS_SHOWSELALWAYS | TVS_SINGLEEXPAND | WS_HSCROLL | WS_TABSTOP,7,7,98,142
END
IDD_OPTIONS_CONSOLE DIALOGEX 0, 0, 277, 142
STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
CONTROL "Take Control",IDC_CHECK_TC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,21,21,57,10
GROUPBOX "Console",IDC_STATIC_CONSOLE,7,7,134,66
COMBOBOX IDC_COMBO_CONSOLE_COLOR,50,56,85,63,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
LTEXT "Color",IDC_STATIC,17,59,18,8
END
IDD_OPTIONS_GENERAL DIALOGEX 0, 0, 277, 142
STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
LTEXT "GENERAL OPTION",IDC_STATIC,89,73,59,8
END
OptionsDialog
//GLOBAL VARIABLES
#define IDT_TIMER_PANEL 77
HWND hDlgOpt;
HWND hDlgPanelGeneral = NULL;
HWND hDlgPanelConsole = NULL;
UINT iPanelSelect = 1;
//HANDLE MESSAGES FROM GENERAL PANEL
LRESULT CALLBACK PanelGeneral(HWND hDlgPanel, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
{
return TRUE;
}
}
return FALSE;
}
//HANDLE MESSAGES FROM CONSOLE PANEL
LRESULT CALLBACK PanelConsole(HWND hDlgPanel, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
{
//INIT CONSOLE PANEL CONTROLS
return TRUE;
}
}
return FALSE;
}
//HANDLE MESSAGES FROM OPTIONS DIALOG
LRESULT CALLBACK Options(HWND hDlgOptions, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
{
hDlgOpt = hDlgOptions;
//LOAD PANEL GENERAL
HRSRC hrsrc = FindResourceEx(hInst, (LPCWSTR)RT_DIALOG, (LPCWSTR)IDD_OPTIONS_GENERAL, iLanguage);
HGLOBAL hglb = LoadResource(hInst, hrsrc);
LPVOID lpsz = LockResource(hglb);
hDlgPanelGeneral = CreateDialogIndirectW(GetModuleHandleW(NULL), lpsz, hDlgOptions, (DLGPROC)PanelGeneral);
//LOAD PANEL CONSOLE
hrsrc = FindResourceEx(hInst, (LPCWSTR)RT_DIALOG, (LPCWSTR)IDD_OPTIONS_CONSOLE, iLanguage);
hglb = LoadResource(hInst, hrsrc);
lpsz = LockResource(hglb);
hDlgPanelConsole = CreateDialogIndirectW(GetModuleHandleW(NULL), lpsz, hDlgOptions, (DLGPROC)PanelConsole);
//Await the animation window for displaying TreeView and Panel
SetTimer(hDlgOptions, IDT_TIMER_PANEL, 300, (TIMERPROC) NULL);
//TRY TO SET DEFAUT ID TO TREEVIEW
//SendMessage(hDlgOptions, DM_SETDEFID, IDC_TREE, 0);
//TRY TO FOCUS ON TREEVIEW
//SendMessage(hDlgOptions, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hDlgOptions, IDC_TREE), TRUE);
//INIT CONTROLS
if (bSaveConfig == TRUE)
{
EnableOptionsControls(hDlgPanelConsole);
SendMessage(GetDlgItem(hDlgOptions, IDC_CHECK_SAVE_CONFIG), BM_SETCHECK, BST_CHECKED, 0);
}
else
{
DisableOptionsControls(hDlgPanelConsole);
}
return TRUE;
}
case WM_NOTIFY:
{
switch (LOWORD(wParam))
{
case IDC_TREE:
NotifyTreeView(hDlgOptions, lParam, wParam);
break;
}
return TRUE;
}
case WM_MOVE:
{
//MAYBE ONLY USE WM_MOVING
UINT xPos = (UINT)LOWORD(lParam);
UINT yPos = (UINT)HIWORD(lParam);
SetWindowPos(hDlgPanelGeneral, HWND_TOP, xPos + 162, yPos + 11, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
SetWindowPos(hDlgPanelConsole, HWND_TOP, xPos + 162, yPos + 11, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
switch (iPanelSelect)
{
case 1: ShowWindow(hDlgPanelGeneral, SW_SHOW); break;
case 2: ShowWindow(hDlgPanelConsole, SW_SHOW); break;
}
return TRUE;
}
case WM_MOVING:
{
//MAYBE BEST MOVING PANEL WITH THE DIALOG
//BUT WIN7 HIDE THE CONTENT...
//NOW HIDE WHEN MOVING
ShowWindow(hDlgPanelGeneral, SW_HIDE);
ShowWindow(hDlgPanelConsole, SW_HIDE);
return TRUE;
}
case WM_TIMER:
{
switch (wParam)
{
case IDT_TIMER_PANEL:
//LOAD TREEVIEW
InitTreeView(hDlgOptions);
KillTimer(hDlgOptions, IDT_TIMER_PANEL);
}
return FALSE;
}
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case ID_BUTTON_SAVE:
case IDOK:
case IDCANCEL:
{
EndDialog(hDlgOptions, LOWORD(wParam));
return TRUE;
}
break;
}
}
}
return FALSE;
}
void EnableOptionsControls(HWND hDlgOptions)
{
EnableWindow(GetDlgItem(hDlgOptions, IDC_CHECK_TC), TRUE);
EnableWindow(GetDlgItem(hDlgOptions, IDC_COMBO_CONSOLE_COLOR), TRUE);
}
void DisableOptionsControls(HWND hDlgOptions)
{
EnableWindow(GetDlgItem(hDlgOptions, IDC_CHECK_TC), FALSE);
EnableWindow(GetDlgItem(hDlgOptions, IDC_COMBO_CONSOLE_COLOR), FALSE);
}
void InitTreeView(HWND hDlgOptions)
{
TV_INSERTSTRUCT tviis;
HTREEITEM hitem;
HIMAGELIST hImageList;
HWND hTreeView;
hTreeView = GetDlgItem(hDlgOptions, IDC_TREE);
hImageList = ImageList_LoadImage(hInst, MAKEINTRESOURCE(IDB_BITMAP_TV), 16, 16,
CLR_DEFAULT, IMAGE_BITMAP, LR_CREATEDIBSECTION | LR_DEFAULTSIZE | LR_DEFAULTCOLOR);
TreeView_SetImageList(hTreeView, hImageList, TVSIL_NORMAL);
ZeroMemory(&(tviis.item), sizeof(TV_ITEM));
tviis.hInsertAfter = TVI_LAST;
tviis.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
tviis.hParent = TVI_ROOT;
tviis.item.iImage = 0;
tviis.item.iSelectedImage = 1;
tviis.item.lParam = 1;
tviis.item.pszText = L"General";
hitem = TreeView_InsertItem(hTreeView, &tviis);
tviis.hParent = hitem;
tviis.item.iImage = 2;
tviis.item.iSelectedImage = 2;
tviis.item.lParam = 3;
tviis.item.pszText = L"Dialog";
TreeView_InsertItem(hTreeView, &tviis);
tviis.item.iImage = 3;
tviis.item.iSelectedImage = 3;
tviis.item.lParam = 4;
tviis.item.pszText = L"Color";
TreeView_InsertItem(hTreeView, &tviis);
//SELECT THE FIRST ITEM
TreeView_SelectItem(hTreeView, hitem);
TreeView_Expand(hTreeView, hitem, TVE_EXPAND);
tviis.hParent = TVI_ROOT;
tviis.item.iImage = 0;
tviis.item.iSelectedImage = 1;
tviis.item.lParam = 2;
tviis.item.pszText = L"Console";
hitem = TreeView_InsertItem(hTreeView, &tviis);
tviis.hParent = hitem;
tviis.item.iImage = 3;
tviis.item.iSelectedImage = 3;
tviis.item.lParam = 5;
tviis.item.pszText = L"Color";
TreeView_InsertItem(hTreeView, &tviis);
tviis.item.iSelectedImage = 2;
tviis.item.iImage = 2;
tviis.item.lParam = 6;
tviis.item.pszText = L"Action";
TreeView_InsertItem(hTreeView, &tviis);
}
void NotifyTreeView(HWND hDlgOptions, LPARAM lParam, WPARAM wParam)
{
LPNMTREEVIEW pnm = (LPNMTREEVIEW)lParam;
//NOTIFY WHEN SELECTION IS CHANGE
if (((LPNMHDR)lParam)->code == TVN_SELCHANGED)
{
RECT wRECT;
GetWindowRect(hDlgOptions, &wRECT);
TVITEM tvi;
HTREEITEM Selected = NULL;
WCHAR Text[255] = { 0 };
Selected = TreeView_GetSelection(GetDlgItem(hDlgOptions, IDC_TREE));
if (Selected == NULL)
return;
ZeroMemory(&tvi, sizeof(tvi));
tvi.mask = TVIF_TEXT;
tvi.pszText = Text;
tvi.cchTextMax = 256;
tvi.hItem = Selected;
//CHANGE THE PANEL WITH THE SELECT ITEM
if (TreeView_GetItem(GetDlgItem(hDlgOptions, IDC_TREE), &tvi))
{
if (wcscmp(tvi.pszText, L"General") == 0)
{
iPanelSelect = 1;
ShowWindow(hDlgPanelConsole, SW_HIDE);
SetWindowPos(hDlgPanelGeneral, HWND_TOP, wRECT.left + 165, wRECT.top + 36, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW);
return;
}
if (wcscmp(tvi.pszText, L"Console") == 0)
{
iPanelSelect = 2;
ShowWindow(hDlgPanelGeneral, SW_HIDE);
SetWindowPos(hDlgPanelConsole, HWND_TOP, wRECT.left + 165, wRECT.top + 36, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW);
return;
}
}
}
}

The tab order is defined by the order your controls are listed in the rc file. Just move your
CONTROL "",IDC_TREE,...
line to be the first after BEGIN.
I am not sure what animation are you talking about. The timer is an OK way to delay something if there is a specific time interval. If you simply want to defer initialization of the Tree control until after everything is created and displayed, I would post some command message, and do everything in its handler.

Related

DS_CONTROL | WS_CHILD combination causes infinite loop

Hello.I'm trying to create a "dialog in dialog" example using the WinAPI and C. This example consists in a child dialog with an autocheckbox, and a main dialog containing a static black rectangle which is the parent for the child dialog and a push button that shows in a message box a text with the checkbox status.When I set the flags DS_CONTROL | WS_CHILD for the child dialog, whenever I try to change the checkbox status the application enters into an infinite loop and I have to force close it. When I remove the DS_CONTROL flag, works as intended but I cannot cycle between the controls using the tab key.What can I do in order to make it work as intended using the DS_CONTROL flag?Here's the content of my main.c file:
#include <windows.h>
#pragma comment (lib, "user32")
HINSTANCE hInst;
BOOL isChecked;
const unsigned char checkedStr[] = "Checkbox is checked";
const unsigned char notCheckedStr[] = "Checkbox is not checked";
BOOL CALLBACK ChildDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_COMMAND:
switch (LOWORD(wParam))
{
case 21:
isChecked = IsDlgButtonChecked(hwndDlg, 21);
return TRUE;
}
return FALSE;
}
return FALSE;
}
BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_INITDIALOG:
{
HWND hContainer, hChilddDlg;
hContainer = GetDlgItem(hwndDlg, 11);
hChilddDlg = CreateDialogParam(hInst, MAKEINTRESOURCE(20), hContainer, ChildDlgProc, 0);
ShowWindow(hChilddDlg, SW_SHOW);
return TRUE;
}
case WM_COMMAND:
switch (LOWORD(wParam))
{
case 12:
{
const unsigned char *ptr;
if (isChecked)
{
ptr = checkedStr;
}
else
{
ptr = notCheckedStr;
}
MessageBox(hwndDlg, ptr, TEXT("Checkbox status"), MB_OK | MB_ICONINFORMATION);
return TRUE;
}
}
return FALSE;
case WM_CLOSE:
EndDialog(hwndDlg, 0);
return TRUE;
}
return FALSE;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
hInst = hInstance;
isChecked = FALSE;
return DialogBoxParam(hInstance, MAKEINTRESOURCE(10), NULL, DialogProc, 0);
}
And here's the content of my rsrc.rcfile:
#include <windows.h>
10 DIALOGEX 0, 0, 130, 47
STYLE DS_CENTER | DS_SETFONT | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU
CAPTION "Checkbox status"
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
FONT 9, "Segoe UI"
{
CONTROL "", 11, STATIC, SS_BLACKRECT | WS_CHILD | WS_VISIBLE, 5, 5, 120, 20
CONTROL "&Status", 12, BUTTON, BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 75, 30, 50, 12
}
20 DIALOGEX 0, 0, 120, 20
STYLE DS_SETFONT | DS_CONTROL | WS_CHILD
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
FONT 9, "Segoe UI"
{
CONTROL "Checkbox", 21, BUTTON, BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0, 5, 50, 10
}
I compile it in the Visual C++ command prompt with: cl /c main.c && rc rsrc.rc && link /SUBSYSTEM:WINDOWS /OUT:test.exe main.obj rsrc.res.Thanks in advance for your help.
Found the solution in the NSIS source code. The problem was that I was putting the child dialog as a child of the blackrect so it was out of the event loop of the main dialog, causing the hang. In order to solve this I had to put it as a child of the main dialog and move it over the blackrect.Here's the updated code of the WM_INITDIALOG case in the main dialog proc:
// ...
case WM_INITDIALOG:
{
HWND hChilddDlg;
hChilddDlg = CreateDialogParam(hInst, MAKEINTRESOURCE(20), hwndDlg, ChildDlgProc, 0);
if (hChilddDlg)
{
RECT rect;
GetWindowRect(GetDlgItem(hwndDlg, 11), &rect);
ScreenToClient(hwndDlg, (LPPOINT)&rect);
SetWindowPos(hChilddDlg, 0, rect.left, rect.top, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
ShowWindow(hChilddDlg, SW_SHOWNA);
}
return TRUE;
}
// ...
With this I was able to use the DS_CONTROL flag and tab cycle between controls.

MDI child window and status bar C win32 API [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I am creating an MDI Child Window after selecting "File -> Open" Menu.
In the "Open" switch statement I have the window creation function
HWND hwndChild = CreateWindowEx(WS_EX_MDICHILD, childClass, "MDI child", WS_CLIPCHILDREN, 0, 0, 400, 300, hWndClient, MAKEINTRESOURCE(IDM_FIRSTCHILD), GetModuleHandle(NULL), 0);
After that declaration I expected the child MDI window to show but nothing happens. The window handle hwndChild is also different from NULL and the error MessageBox doesn't show.
It seems that the error is in handling the WM_SIZE message inside the WndProc window function.
One solution is to put
return DefFrameProc(hwnd, hWndClient, msg, wParam, lParam);
instead of
return 0;
at the end of WndProc. But this solution is not compatible with the status bar, as it then disappears.
Here is the complete code:
#include <windows.h>
#include <commctrl.h> //per SBARS_SIZEGRIP e STATUSCLASSNAME
#define IDM_OPEN 100
#define IDM_EXIT 101
#define IDM_ABOUT 102
#define IDC_STATUSBAR 103
#define IDM_ARRANGE 104
#define IDM_CASCADE 105
#define IDM_TILE 106
#define IDM_CLOSEALL 107
#define IDM_CLOSE 108
#define ID_CLIENTWND 109
#define IDM_FIRSTCHILD 5000
const char frameClass[] = "myFrameClass";
const char clientClass[] = "mdiclient"; //funziona solo con "mdiclient"
const char childClass[] = "myChildClass";
HWND hWndStatusBar;
HWND hWndClient;
//STEP 5 Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam){
switch (msg){
case WM_CREATE:
//STEP 6: Create Status Bar
hWndStatusBar = CreateWindowEx(0,STATUSCLASSNAME,NULL,
WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP,
0, 0, 0, 0,
hwnd,
(HMENU)IDC_STATUSBAR,
(HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), NULL);
if(!hWndStatusBar){
MessageBox(NULL, "Failed To Create The Status Bar", "Error", MB_OK | MB_ICONERROR);
return 0;
}
// Establish the number of partitions or 'parts' the status bar will
// have, their actual dimensions will be set in the parent window's
// WM_SIZE handler.
RECT rc;
GetClientRect(hwnd, &rc);
int nHalf = rc.right / 2;
int nParts[4] = { nHalf, nHalf + nHalf / 3, nHalf + nHalf * 2 / 3, -1 };
SendMessage(hWndStatusBar, SB_SETPARTS, 4, (LPARAM)&nParts);
//crea la finestra CLIENT
CLIENTCREATESTRUCT ccs;
// Assign the 'Window' menu.
ccs.hWindowMenu = GetSubMenu(GetMenu(hwnd), 1); // uno perchè così la finestra appare nel secondo menu (partendo da zero) ovvero nel menu 'Windows'
ccs.idFirstChild = IDM_FIRSTCHILD;
// Create the client window. (quella che contiene i child!!)
hWndClient = CreateWindowEx(WS_EX_CLIENTEDGE, clientClass,//FUNZIONA SOLO CON "mdiclient"
NULL,
WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,
0, 0, 0, 0,
hwnd,(HMENU)ID_CLIENTWND/*GetMenu(hwnd)*/,GetModuleHandle(NULL),&ccs);
if(hWndClient == NULL) {
MessageBox(NULL, "Client Window Creation Failed!","Error!",MB_ICONEXCLAMATION|MB_OK);
return 0;
}
break;
case WM_SIZE:
//resize the parts
GetClientRect(hwnd, &rc);
nHalf = rc.right / 2;
nParts[0] = nHalf; nParts[1] = nHalf + nHalf / 3; nParts[2] = nHalf + nHalf * 2 / 3; nParts[3] = -1;
SendMessage(hWndStatusBar, SB_SETPARTS, 4, (LPARAM)&nParts);
//resize the statusbar
SendMessage(GetDlgItem(hwnd, IDC_STATUSBAR), WM_SIZE,0,0);
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_COMMAND:
if(LOWORD(wParam) == IDM_EXIT) DestroyWindow(hwnd);
if(LOWORD(wParam) == IDM_ABOUT) MessageBox(hwnd,"ABOUT premuto","ciao",MB_OK);
if(LOWORD(wParam) == IDM_OPEN){
//apre il file...
//TODO
//crea la finestra CHILD
HWND hwndChild = CreateWindowEx(WS_EX_MDICHILD, //extended styles
childClass, //control 'class' name
"MDI child", //control caption
WS_CLIPCHILDREN, //control style
0, //position: left
0, //position: top
400, //width
300, //height
hWndClient, //parent window handle
//control's ID
MAKEINTRESOURCE(IDM_FIRSTCHILD),
GetModuleHandle(NULL), //application instance
0); //user defined info
if(hwndChild == NULL){
MessageBox(hwnd,"Impossibile creare la finestra Child","Errore",MB_ICONERROR);
}
}
break;
default:
//return DefWindowProc(hwnd,msg,wParam,lParam);
return DefFrameProc(hwnd, hWndClient, msg, wParam, lParam); //per tenere conto delle finestre figlie
}
return 0;
}
LRESULT CALLBACK ChildWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
switch(msg) {
case WM_CREATE :
// LPCREATESTRUCT lpCreateStruct = (LPCREATESTRUCT)lParam;
// LPMDICREATESTRUCT lpMDICreateStruct = (LPMDICREATESTRUCT)lpCreateStruct->lpCreateParams;
// FrameParam = lpMDICreateStruct->lParam;
break;
case WM_COMMAND:
break;
/* All other messages (a lot of them) are processed using default procedures */
default:
return DefMDIChildProc(hwnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
WNDCLASSEX wc;
HWND hwnd;
MSG msg;
//STEP 1: Registering Frame Class Window
wc.cbSize = sizeof(WNDCLASSEX);
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_APPWORKSPACE+1);//(COLOR_WINDOW);
wc.hIconSm = LoadIcon(NULL,IDI_APPLICATION);
wc.lpszMenuName = NULL;
wc.lpszClassName = frameClass;
if(!RegisterClassEx(&wc)){
MessageBox(NULL,"Frame Window Registration Failed!","Error!",MB_ICONEXCLAMATION);
return 0;
}
//la classe CLIENT non la devo registrare?
//STEP 1.2: Registering Child Class Window
wc.lpfnWndProc = (WNDPROC)ChildWndProc;
wc.hIcon = (HICON)LoadImage(0,IDI_APPLICATION,IMAGE_ICON,0,0,LR_SHARED);
wc.hIconSm = LoadImage(hInstance,childClass,IMAGE_ICON,16,16,LR_DEFAULTCOLOR);
wc.hCursor = (HCURSOR)LoadImage(0,IDC_ARROW,IMAGE_CURSOR,0,0,LR_SHARED);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);//(COLOR_WINDOW);
wc.lpszMenuName = NULL;
wc.lpszClassName = childClass;
if(!RegisterClassEx(&wc)){
MessageBox(NULL,"Child Window Registration Failed!","Error!",MB_ICONEXCLAMATION);
return 0;
}
//STEP 2: Creating the Window
hwnd = CreateWindowEx(WS_EX_CLIENTEDGE,
frameClass,
"046 - Visualizer",
WS_VISIBLE|WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,600,400,
NULL,NULL,hInstance,NULL);
if(hwnd == NULL){
MessageBox(NULL,"Frame Window Creation Failed!","Error!",MB_ICONEXCLAMATION);
return 0;
}
ShowWindow(hwnd,nCmdShow);
UpdateWindow(hwnd);
//STEP 3: Create Menu
HMENU hMenu = CreateMenu(); //crea un menu vuoto
HMENU hSubMenu; //variabile usata per aggiungere sottomenu ti tipo POPUP
hSubMenu = CreatePopupMenu();
AppendMenu(hSubMenu,MF_STRING,IDM_OPEN,"&Open");
AppendMenu(hSubMenu,MF_STRING,IDM_CLOSE,"&Close");
AppendMenu(hSubMenu, MF_SEPARATOR, 0, NULL);
AppendMenu(hSubMenu,MF_STRING,IDM_EXIT,"&Exit");
AppendMenu(hMenu,MF_STRING|MF_POPUP,(UINT)hSubMenu,"&File"); //aggiunge il sottomenu al menu
hSubMenu = CreatePopupMenu();
AppendMenu(hSubMenu,MF_STRING,IDM_ARRANGE,"Arrange");
AppendMenu(hSubMenu,MF_STRING,IDM_CASCADE,"Cascade");
AppendMenu(hSubMenu,MF_STRING,IDM_TILE,"Tile");
AppendMenu(hSubMenu,MF_STRING,IDM_CLOSEALL,"Close All");
AppendMenu(hMenu,MF_STRING|MF_POPUP,(UINT)hSubMenu,"&Windows");
hSubMenu = CreatePopupMenu();
AppendMenu(hSubMenu,MF_STRING,IDM_ABOUT,"&About");
AppendMenu(hMenu,MF_STRING|MF_POPUP,(UINT)hSubMenu,"&Help");
if(hMenu == NULL){
MessageBox(NULL,"Menu Creation Failed!","Error!",MB_ICONEXCLAMATION);
return 0;
}
SetMenu(hwnd,hMenu); //setta il menu sulla finestra
//STEP 4: Message Loop
while(GetMessage(&msg,NULL,0,0) > 0){
if(hWndClient && TranslateMDISysAccel(hWndClient,&msg)) continue; //process the predefined MDI specific accelerator keys
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
To handle WM_SIZE in MDI frame, see documentation for DefFrameProc
WM_SIZE
Resizes the MDI client window to fit in the new frame window's client
area. If the frame window procedure sizes the MDI client window to a
different size, it should not pass the message to the DefWindowProc
function.
If you are resizing the frame's client are, return zero. If you are not resizing then pass to DefWindowProc (not DefFrameProc)
To create a MDI child window, use MDICREATESTRUCT and SendMessage( ... WM_MDICREATE ... ), instead of CreateWindowEx(WS_EX_MDICHILD...
Suggestion to fix the procedure:
I am using a slightly different method to handle defaults. Also IDM_EXIT should call WM_CLOSE
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static MDICREATESTRUCT mdicreate;
static HINSTANCE hinstance;
switch(msg)
{
case WM_CREATE:
{
hinstance = (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE);
CLIENTCREATESTRUCT ccs = { 0 };
ccs.hWindowMenu = GetSubMenu(GetMenu(hwnd), 1);
ccs.idFirstChild = IDM_FIRSTCHILD;
hWndClient = CreateWindow("MDICLIENT", "",
WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,
0, 0, 0, 0, hwnd, NULL, 0, &ccs);
CreateWindow(STATUSCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP,
0, 0, 0, 0, hwnd, (HMENU)IDC_STATUSBAR, hinstance, NULL);
return 0;
}
case WM_SIZE:
{
RECT rc;
GetClientRect(hwnd, &rc);
int nHalf = rc.right / 2;
int nParts[4];
nParts[0] = nHalf;
nParts[1] = nHalf + nHalf / 3;
nParts[2] = nHalf + nHalf * 2 / 3;
nParts[3] = -1;
SendMessage(GetDlgItem(hwnd, IDC_STATUSBAR), SB_SETPARTS, 4, (LPARAM)&nParts);
SendMessage(GetDlgItem(hwnd, IDC_STATUSBAR), WM_SIZE, 0, 0);
RECT statusRect;
GetClientRect(GetDlgItem(hwnd, IDC_STATUSBAR), &statusRect);
rc.bottom -= statusRect.bottom;
MoveWindow(hWndClient, 0, 0, rc.right, rc.bottom, TRUE);
return 0;
}
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_COMMAND:
if(LOWORD(wParam) == IDM_EXIT)
{
SendMessage(hwnd, WM_CLOSE, 0, 0);
return 0;
}
if(LOWORD(wParam) == IDM_ABOUT)
MessageBox(hwnd, "ABOUT premuto", "ciao", MB_OK);
if(LOWORD(wParam) == IDM_OPEN)
{
mdicreate.szClass = childClass;
mdicreate.szTitle = "Title";
mdicreate.hOwner = hinstance;
mdicreate.x = CW_USEDEFAULT; //change this to a small number
mdicreate.y = CW_USEDEFAULT;
mdicreate.cx = CW_USEDEFAULT;
mdicreate.cy = CW_USEDEFAULT;
mdicreate.style = 0;
mdicreate.lParam = 0;
SendMessage(hWndClient, WM_MDICREATE, 0, (LPARAM)
(LPMDICREATESTRUCT)&mdicreate);
}
break;
}
return DefFrameProc(hwnd, hWndClient, msg, wParam, lParam);
}
I have solved sizing the MDI client area in WM_SIZE routine.
I'm posting the answer and don't delete the question because it may help someone else with my problem in future.
I have put
return DefFrameProc(hwnd, hWndClient, msg, wParam, lParam);
at the end of WndProc and added the code for resizing MDI client window that calculate also the presence of the status bar:
// get client area of frame window
RECT clientRect;
GetClientRect(hwnd, &clientRect);
int frame_dx = clientRect.right - clientRect.left;
int frame_dy = clientRect.bottom - clientRect.top;
// get client area of status bar
RECT statusRect;
GetClientRect(hWndStatusBar, &statusRect);
int status_dy = statusRect.bottom - statusRect.top;
// position the MDIClient such that it doesn't overlap with status bar
MoveWindow(hWndClient, 0, 0, frame_dx, frame_dy - status_dy, TRUE);
//resize the statusbar
SendMessage(GetDlgItem(hwnd, IDC_STATUSBAR), WM_SIZE,0,0);
return 0;
At the end I have put return 0; because the WndProc have not to return DefFrameProc and automatically size MDI client over the whole client area, and also over the status bar making it disappear.
I post the whole corrected source code here:
#include <windows.h>
#include <commctrl.h> //per SBARS_SIZEGRIP e STATUSCLASSNAME
#define IDM_OPEN 100
#define IDM_EXIT 101
#define IDM_ABOUT 102
#define IDC_STATUSBAR 103
#define IDM_ARRANGE 104
#define IDM_CASCADE 105
#define IDM_TILE 106
#define IDM_CLOSEALL 107
#define IDM_CLOSE 108
#define ID_CLIENTWND 109
#define IDM_FIRSTCHILD 5000
const char frameClass[] = "myFrameClass";
const char clientClass[] = "mdiclient"; //funziona solo con "mdiclient"
const char childClass[] = "myChildClass";
HWND hWndStatusBar = NULL;
HWND hWndClient = NULL;
//STEP 5 Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam){
switch (msg){
case WM_CREATE:
{
//STEP 6: Create Status Bar
hWndStatusBar = CreateWindowEx(0,STATUSCLASSNAME,NULL,
WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP,
0, 0, 0, 0,
hwnd,
(HMENU)IDC_STATUSBAR,
(HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), NULL);
if(!hWndStatusBar){
MessageBox(NULL, "Failed To Create The Status Bar", "Error", MB_OK | MB_ICONERROR);
return 0;
}
// Establish the number of partitions or 'parts' the status bar will
// have, their actual dimensions will be set in the parent window's
// WM_SIZE handler.
RECT rc;
GetClientRect(hwnd, &rc);
int nHalf = rc.right / 2;
int nParts[4] = { nHalf, nHalf + nHalf / 3, nHalf + nHalf * 2 / 3, -1 };
SendMessage(hWndStatusBar, SB_SETPARTS, 4, (LPARAM)&nParts);
//crea la finestra CLIENT
CLIENTCREATESTRUCT ccs;
// Assign the 'Window' menu.
ccs.hWindowMenu = GetSubMenu(GetMenu(hwnd), 1); // uno perchè così la finestra appare nel secondo menu (partendo da zero) ovvero nel menu 'Windows'
ccs.idFirstChild = IDM_FIRSTCHILD;
// Create the client window. (quella che contiene i child!!)
hWndClient = CreateWindowEx(WS_EX_CLIENTEDGE, clientClass,//FUNZIONA SOLO CON "mdiclient"
NULL,
WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,
0, 0, 0, 0,
hwnd,(HMENU)ID_CLIENTWND/*GetMenu(hwnd)*/,GetModuleHandle(NULL),&ccs);
if(hWndClient == NULL) {
MessageBox(NULL, "Client Window Creation Failed!","Error!",MB_ICONEXCLAMATION|MB_OK);
return 0;
}
break;
}
case WM_SIZE:
{
//resize the parts
RECT rc;
GetClientRect(hwnd, &rc);
int nHalf = rc.right / 2;
int nParts[4] = { nHalf, nHalf + nHalf / 3, nHalf + nHalf * 2 / 3, -1 };
SendMessage(hWndStatusBar, SB_SETPARTS, 4, (LPARAM)&nParts);
//resize MDI
// get client area of frame window
RECT clientRect;
GetClientRect(hwnd, &clientRect);
int frame_dx = clientRect.right - clientRect.left;
int frame_dy = clientRect.bottom - clientRect.top;
// get client area of status bar
RECT statusRect;
GetClientRect(hWndStatusBar, &statusRect);
int status_dy = statusRect.bottom - statusRect.top;
// position the MDIClient such that it doesn't overlap with status bar
MoveWindow(hWndClient, 0, 0, frame_dx, frame_dy - status_dy, TRUE);
//resize the statusbar
SendMessage(GetDlgItem(hwnd, IDC_STATUSBAR), WM_SIZE,0,0);
return 0; //ritorna zero altrimenti la Frame Window ridisegna il MDI client spalmandolo su tutta la client area andando sopra alla status bar
}
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_COMMAND:
if(LOWORD(wParam) == IDM_EXIT) DestroyWindow(hwnd);
if(LOWORD(wParam) == IDM_ABOUT) MessageBox(hwnd,"ABOUT premuto","ciao",MB_OK);
if(LOWORD(wParam) == IDM_OPEN){
//apre il file...
//TODO
//crea la finestra CHILD
// HWND hwndChild = CreateWindowEx(WS_EX_MDICHILD, //extended styles
// childClass, //control 'class' name
// "MDI child", //control caption
// WS_CLIPCHILDREN|WS_CLIPSIBLINGS, //control style
// 0, //position: left
// 0, //position: top
// 400, //width
// 300, //height
// hWndClient, //parent window handle
// //control's ID
// MAKEINTRESOURCE(IDM_FIRSTCHILD),
// GetModuleHandle(NULL), //application instance
// 0); //user defined info
//
// if(hwndChild == NULL){
// MessageBox(hwnd,"Impossibile creare la finestra Child","Errore",MB_ICONERROR);
// }
//metodo alternativo da StackOverflow
MDICREATESTRUCT mdicreate = {0};
mdicreate.szClass = childClass;
mdicreate.szTitle = "class_mdichild";
mdicreate.hOwner = (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE); // <- hinstance
mdicreate.x = CW_USEDEFAULT;
mdicreate.y = CW_USEDEFAULT;
mdicreate.cx = CW_USEDEFAULT;
mdicreate.cy = CW_USEDEFAULT;
mdicreate.style = 0;
mdicreate.lParam = 0;
HWND hwndChild = (HWND)SendMessage(hWndClient, WM_MDICREATE, 0,(LPARAM)(LPMDICREATESTRUCT)&mdicreate);
if(hwndChild == NULL) {
MessageBox(hwnd, "Impossibile creare la finestra Child", "Errore", MB_ICONERROR);
}
}
break;
default:
//return DefWindowProc(hwnd,msg,wParam,lParam);
return DefFrameProc(hwnd, hWndClient, msg, wParam, lParam); //per tenere conto delle finestre figlie
}
return DefFrameProc(hwnd, hWndClient, msg, wParam, lParam);
}
LRESULT CALLBACK ChildWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
switch(msg) {
case WM_CREATE :
// LPCREATESTRUCT lpCreateStruct = (LPCREATESTRUCT)lParam;
// LPMDICREATESTRUCT lpMDICreateStruct = (LPMDICREATESTRUCT)lpCreateStruct->lpCreateParams;
// FrameParam = lpMDICreateStruct->lParam;
break;
case WM_COMMAND:
break;
/* All other messages (a lot of them) are processed using default procedures */
default:
return DefMDIChildProc(hwnd, msg, wParam, lParam);
}
return DefMDIChildProc(hwnd, msg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
WNDCLASSEX wc;
HWND hwnd;
MSG msg;
//STEP 1: Registering Frame Class Window
wc.cbSize = sizeof(WNDCLASSEX);
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_APPWORKSPACE+1);//(COLOR_WINDOW);
wc.hIconSm = LoadIcon(NULL,IDI_APPLICATION);
wc.lpszMenuName = NULL;
wc.lpszClassName = frameClass;
if(!RegisterClassEx(&wc)){
MessageBox(NULL,"Frame Window Registration Failed!","Error!",MB_ICONEXCLAMATION);
return 0;
}
//la classe CLIENT non la devo registrare?
//STEP 1.2: Registering Child Class Window
wc.lpfnWndProc = (WNDPROC)ChildWndProc;
wc.hIcon = (HICON)LoadImage(0,IDI_APPLICATION,IMAGE_ICON,0,0,LR_SHARED);
wc.hIconSm = LoadImage(hInstance,childClass,IMAGE_ICON,16,16,LR_DEFAULTCOLOR);
wc.hCursor = (HCURSOR)LoadImage(0,IDC_ARROW,IMAGE_CURSOR,0,0,LR_SHARED);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);//(COLOR_WINDOW);
wc.lpszMenuName = NULL;
wc.lpszClassName = childClass;
if(!RegisterClassEx(&wc)){
MessageBox(NULL,"Child Window Registration Failed!","Error!",MB_ICONEXCLAMATION);
return 0;
}
//STEP 2: Creating the Window
hwnd = CreateWindowEx(WS_EX_CLIENTEDGE,
frameClass,
"046 - Visualizer",
WS_VISIBLE|WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,600,400,
NULL,NULL,hInstance,NULL);
if(hwnd == NULL){
MessageBox(NULL,"Frame Window Creation Failed!","Error!",MB_ICONEXCLAMATION);
return 0;
}
ShowWindow(hwnd,nCmdShow);
UpdateWindow(hwnd);
//STEP 3: Create Menu
HMENU hMenu = CreateMenu(); //crea un menu vuoto
HMENU hSubMenu; //variabile usata per aggiungere sottomenu ti tipo POPUP
hSubMenu = CreatePopupMenu();
AppendMenu(hSubMenu,MF_STRING,IDM_OPEN,"&Open");
AppendMenu(hSubMenu,MF_STRING,IDM_CLOSE,"&Close");
AppendMenu(hSubMenu, MF_SEPARATOR, 0, NULL);
AppendMenu(hSubMenu,MF_STRING,IDM_EXIT,"&Exit");
AppendMenu(hMenu,MF_STRING|MF_POPUP,(UINT)hSubMenu,"&File"); //aggiunge il sottomenu al menu
hSubMenu = CreatePopupMenu();
AppendMenu(hSubMenu,MF_STRING,IDM_ARRANGE,"Arrange");
AppendMenu(hSubMenu,MF_STRING,IDM_CASCADE,"Cascade");
AppendMenu(hSubMenu,MF_STRING,IDM_TILE,"Tile");
AppendMenu(hSubMenu,MF_STRING,IDM_CLOSEALL,"Close All");
AppendMenu(hMenu,MF_STRING|MF_POPUP,(UINT)hSubMenu,"&Windows");
hSubMenu = CreatePopupMenu();
AppendMenu(hSubMenu,MF_STRING,IDM_ABOUT,"&About");
AppendMenu(hMenu,MF_STRING|MF_POPUP,(UINT)hSubMenu,"&Help");
if(hMenu == NULL){
MessageBox(NULL,"Menu Creation Failed!","Error!",MB_ICONEXCLAMATION);
return 0;
}
SetMenu(hwnd,hMenu); //setta il menu sulla finestra
//STEP 4: Message Loop
while(GetMessage(&msg,NULL,0,0) > 0){
if(hWndClient && TranslateMDISysAccel(hWndClient,&msg)) continue; //process the predefined MDI specific accelerator keys
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}

No LVN_GETINFOTIP notifications in a LVS_REPORT Listview of text cells

I have a listview of texts and have total control over it, works like a dream.
Except I don't get any LVN_GETINFOTIP notifications by WM_NOTIFY. I get every other notifications message but not LVN_GETINFOTIP.
I have spent some time been Googling and trying whatever I can find. Some sites say that from Vista it works different but not what different. I don’t care if it works before Win10 (can live with it) and not at all if it works before Win7.
I really wonder what prevents the LVN_GETINFOTIP messages?
switch (((LPNMHDR)lParam)->code)
{
case LVN_GETINFOTIP:
CreateListView(
0,
LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP | LVS_EX_LABELTIP,
0,
3 * TAB_HIGHT,
OwnWindowWidth,
OwnWindowHight - (OBJ_WINDOW_HIGHT + (3 * TAB_HIGHT)),
hWnd,
(HMENU)IDC_MAIN_LISTVIEW,
(HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE));
static HWND CreateListView(
DWORD dwAddStyle,
DWORD dwAddExtendedListViewStyle,
int X,
int Y,
int nWidth,
int nHeight,
HWND hWndParent,
HMENU IdListWiew,
HINSTANCE hInst)
{
HWND hWndListView;
INITCOMMONCONTROLSEX icex;
memset(&icex, 0, sizeof(INITCOMMONCONTROLSEX));
// Ensure that the common control DLL is loaded.
icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
icex.dwICC = ICC_LISTVIEW_CLASSES;
InitCommonControlsEx(&icex);
// Create the list-view window in report view with label
// editing enabled.
hWndListView = CreateWindowEx(WS_EX_ACCEPTFILES, WC_LISTVIEW, L"",
WS_CHILD | LVS_REPORT | WS_VISIBLE | WS_BORDER | WM_NOTIFY | dwAddStyle,
X, Y, nWidth, nHeight,
hWndParent, IdListWiew, hInst, NULL);
if (hWndListView == NULL)
return NULL;
ListView_SetExtendedListViewStyle(hWndListView, dwAddExtendedListViewStyle);
return hWndListView;
}
Found the error myself!
The sample code for ListViews I once used hides the first column and so I can't get any TVN_GETINFOTIP because there is nothing to hover (Width of column 0 was 0). I managed to find this by reduction of code in a test program and read it real carefully. A bit embarrassed I asked. But this is coding life.
I have now a very compact sample code 160lines of a report ListView if it comes to use. (I rather this question to be removed).
#include <windows.h>
#include <CommCtrl.h>
#include <wchar.h>
#define IDC_MAIN_LISTVIEW 100
#define MAIN_LISTFIELDS 9
#define MAIN_LISTLINES 78
int iMainFieldsWidth[MAIN_LISTFIELDS] = { 50, 60, 78, 70, 100, 50, 50, 121, 112 };
WORD wMainFieldsAlign[MAIN_LISTFIELDS] = { LVCFMT_RIGHT,LVCFMT_LEFT, LVCFMT_LEFT,LVCFMT_LEFT,LVCFMT_LEFT, LVCFMT_RIGHT, LVCFMT_RIGHT, LVCFMT_LEFT, LVCFMT_LEFT };
WCHAR *pMainFieldsHeader[MAIN_LISTFIELDS] = { L"zero",L"one",L"Two",L"Three",L"Four",L"five",L"six",L"seven",L"eight" };
LRESULT WINAPI MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
{
CREATESTRUCT MainWindowCreateStruct;
WNDCLASS wc;
MSG msg;
HWND hWnd;
if (!hPrevInstance)
{
wc.lpszClassName = L"AppClass";
wc.lpfnWndProc = MainWndProc;
wc.style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hInstance, L"1");
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_ACTIVEBORDER + 1);
wc.lpszMenuName = L"AppMenu";
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
RegisterClass(&wc);
}
memset(&MainWindowCreateStruct, 0, sizeof(CREATESTRUCT));
hWnd = CreateWindowEx(WS_EX_ACCEPTFILES, L"AppClass",
L"LvTest",
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
&MainWindowCreateStruct
);
ShowWindow(hWnd, nCmdShow);
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT WINAPI MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CREATE:
{
// Create the list-view window in report view with label
// editing enabled.
HWND hLvWnd = CreateWindowEx(WS_EX_ACCEPTFILES, WC_LISTVIEW, L"",
WS_CHILD | LVS_REPORT | WS_VISIBLE | WS_BORDER,
0, 0, 1000, 500,
hWnd, (HMENU)IDC_MAIN_LISTVIEW, (HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE), NULL);
if (hLvWnd == NULL)
return 0;
ListView_SetExtendedListViewStyle(hLvWnd, LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP | LVS_EX_LABELTIP);
ListView_DeleteAllItems(hLvWnd);
{
LVCOLUMN lvc;
int iCol = 0;
memset(&lvc, 0, sizeof(LVCOLUMN));
while (ListView_DeleteColumn(hLvWnd, 0)); // Nonvisual left column
// Initialize the LVCOLUMN structure.
// The mask specifies that the format, width, text, and
// subitem members of the structure are valid.
lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
// Add the columns.
for (iCol = 0; iCol < MAIN_LISTFIELDS; iCol++)
{
lvc.iSubItem = iCol;
lvc.pszText = pMainFieldsHeader[iCol];
lvc.cchTextMax = MAX_PATH;
lvc.iImage = 0;
lvc.iOrder = 0;
lvc.cx = iMainFieldsWidth[iCol]; // width of column in pixels
lvc.fmt = wMainFieldsAlign[iCol]; // alignment of column
if (ListView_InsertColumn(hLvWnd, lvc.iSubItem, &lvc) == -1)
return 0;
}
}
{
LVITEM lvI;
DWORD index = 0;
memset(&lvI, 0, sizeof(LVITEM));
// Some code to create the list-view control.
// Initialize LVITEM members that are common to all
// items.
lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM | LVIF_STATE | LVIF_INDENT;
lvI.state = 0;
lvI.stateMask = 0;
// Initialize LVITEM members that are different for each item.
for (index = 0; index < MAIN_LISTLINES; index++)
{
lvI.iItem = index;
lvI.iImage = 0; // Icon
lvI.iIndent = 0;
lvI.iSubItem = 0;
// lvI.lParam = (LPARAM) &rgPetInfo[index];
lvI.pszText = LPSTR_TEXTCALLBACK; // sends an
// LVN_GETDISPINFO
// message.
if (ListView_InsertItem(hLvWnd, &lvI) == -1)
return 0;
}
}
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_NOTIFY:
switch (((LPNMHDR)lParam)->code)
{
case LVN_GETINFOTIP:
if (lParam)
{ // This is only working it looks, or actually the LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP | LVS_EX_LABELTIP of the CreateWindowEx isn't, would be nice to have
LPNMLVGETINFOTIP pGetInfoTip = (LPNMLVGETINFOTIP)lParam;
wcscpy(pGetInfoTip->pszText, L"This is an InfoTip Text\nand it takes newlines", pGetInfoTip->cchTextMax);
}
break;
case LVN_GETDISPINFO:
if (lParam)
{
NMLVDISPINFO *plvdi = ((NMLVDISPINFO *)lParam);
if ((plvdi->hdr.hwndFrom == GetDlgItem(hWnd, IDC_MAIN_LISTVIEW)) && (plvdi->item.iSubItem<MAIN_LISTFIELDS) && plvdi->item.cchTextMax)
wcsncpy(plvdi->item.pszText, pMainFieldsHeader[plvdi->item.iSubItem], plvdi->item.cchTextMax);
}
break;
default:
break;
}
break;
default:
return(DefWindowProc(hWnd, msg, wParam, lParam));
}
return 0;
}

DialogBox not rendering correctly?

I'm not sure what I'm doing wrong, but here's how it looks (there's no close button, no caption bar):
It looks as if it's not updating/ticking/repainted.
Here's my Resource.rc file:
#include "resource.h"
#include "windows.h"
#define IDC_STATIC -1
ID_ICON_MAIN ICON "Smile.ico"
ID_DIALOG_ABOUT DIALOG 0, 0, 240, 70
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_BORDER
CAPTION "About"
FONT 8, "Terminal"
{
DEFPUSHBUTTON "&OK", IDOK, 174, 18, 50, 14
PUSHBUTTON "&Cancel", IDCANCEL, 174, 36, 50, 14
GROUPBOX "About this program...", IDC_STATIC, 7, 7, 225, 52
CTEXT "An example program\r\nBy vexe", IDC_STATIC, 16, 18, 144, 33
}
Changing the styles, caption, font size, etc doesn't change anything. Note that I'm using Windows Classic Theme, changing to the standard Windows 7 doesn't help either so it's not a theme issue.
Here's my window code:
#include <Windows.h>
#include "resource.h"
INT_PTR WINAPI DialogWndProc(HWND Window, UINT Message,
WPARAM WParam, LPARAM LParam)
{
INT_PTR Result = TRUE;
switch (Message)
{
case WM_INITDIALOG:
{
// UpdateWindow(Window); // Doesn't really help. Taking out the case didn't do anything either
}
break;
case WM_COMMAND:
{
int Command = LOWORD(WParam);
switch(Command)
{
case IDOK:
{
EndDialog(Window, IDOK);
}
break;
case IDCANCEL:
{
EndDialog(Window, IDCANCEL);
}
break;
default:
{
Result = FALSE;
}
break;
}
}
break;
}
return(Result);
}
LRESULT WINAPI MainWndProc(HWND Window, UINT Message,
WPARAM WParam, LPARAM LParam)
{
LRESULT Result = 0;
switch (Message)
{
// (Causes GetMessage to return false)
case WM_CLOSE:
{
DestroyWindow(Window);
}
break;
case WM_DESTROY:
{
PostQuitMessage(0);
}
break;
case WM_COMMAND:
{
int Command = LOWORD(WParam);
switch (Command)
{
case ID_MENU_FILE_EXIT:
{
PostMessage(Window, WM_QUIT, 0, 0);
}
break;
case ID_MENU_HELP_ABOUT:
{
int Choice = DialogBox(0, MAKEINTRESOURCE(ID_DIALOG_ABOUT), Window, DialogWndProc);
switch (Choice)
{
case IDOK: MessageBox(Window, "Okay!", "OK", MB_OK | MB_ICONINFORMATION); break;
case IDCANCEL: MessageBox(Window, "Canceled!", "Cancel", MB_OK | MB_ICONINFORMATION); break;
}
}
break;
}
}
break;
case WM_CREATE:
{
HMENU Menu;
HMENU SubMenu;
// Create the main menu
Menu = CreateMenu();
// Create submenus
{
SubMenu = CreatePopupMenu();
AppendMenu(SubMenu, MF_STRING, ID_MENU_FILE_EXIT, "E&xit");
AppendMenu(Menu, MF_STRING | MF_POPUP, (UINT_PTR)SubMenu, "&File");
SubMenu = CreatePopupMenu();
AppendMenu(SubMenu, MF_STRING, ID_MENU_HELP_ABOUT, "&About");
AppendMenu(Menu, MF_STRING | MF_POPUP, (UINT_PTR)SubMenu, "&Help");
}
// Set the menu on the window
SetMenu(Window, Menu);
}
break;
default:
{
Result = DefWindowProc(Window, Message, WParam, LParam);
}
}
return(Result);
}
int CALLBACK WinMain(HINSTANCE Instance, HINSTANCE Previous, LPSTR CommandLine, int CmdShow)
{
// Create window class
WNDCLASSEX WindowClass = {0};
WindowClass.cbSize = sizeof(WNDCLASSEX);
WindowClass.style = CS_HREDRAW | CS_VREDRAW;
WindowClass.lpfnWndProc = (WNDPROC)MainWndProc;
WindowClass.hInstance = Instance;
WindowClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
WindowClass.lpszMenuName = MAKEINTRESOURCE(ID_MENU_MAIN);
WindowClass.lpszClassName = "SaedoGames_0";
WindowClass.hIcon = LoadIcon(Instance, MAKEINTRESOURCE(ID_ICON_MAIN));
WindowClass.hIconSm = (HICON)LoadImage(0, "Smile.ico", IMAGE_ICON, 16, 16, LR_LOADFROMFILE);
RegisterClassEx(&WindowClass);
// Create window
HWND Window = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, "SaedoGames_0", "Test Window",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT,
640, 480,
0, 0,
Instance, 0
);
// Show window
ShowWindow(Window, CmdShow);
UpdateWindow(Window);
// Message loop
MSG Msg;
while (GetMessage(&Msg, Window, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return(0);
}
Pretty sure I'm missing a simple function call but just not sure what it is. What am I missing?
Your dialog procedure unconditionally returns TRUE to every message, which means "I handled the message, you don't have to do anything else". Your dialog procedure does so by setting Result to TRUE at the top of the function and then never changing it (unless you get a WM_COMMAND from an unknown control). This is wrong; you need to return FALSE if you don't handle a message yourself.
WM_INITDIALOG is one of a handful of messages that return their values directly to the dialog system instead of through DWLP_MSGRESULT. In that case and that case only, you do need to return TRUE (unless you manually adjusted tab stops).

Open image file on button click to rectangle

How to open an image file and put it in the rectangle when a button is clicked? I use winapi and c programming language, please help and thanks in advance
Global Variable :
HDC hdc, hdcMem;
HBITMAP hLogo, hGambar;
OPENFILENAME ofn = {0};
char szNamaFile[MAX_PATH] = {0}
WM_CREATE :
HWND btnLoad;
btnLoad = CreateWindow("Button", "&Load", WS_CHILD | WS_TABSTOP | WS_VISIBLE | BS_FLAT, 149, 421, 70, 25, hWnd, (HMENU)IDB_LOAD, GetModuleHandle(NULL), NULL);
if(btnLoad == NULL)
{
MessageBox(NULL, "Gagal Membuat Button!", "Error Uy!", MB_ICONEXCLAMATION);
exit(EXIT_FAILURE);
}
hGambar = (HBITMAP)LoadImage(hInst, szNamaFile, IMAGE_BITMAP, 5, 5, LR_LOADFROMFILE);
SendMessage(btnLoad, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hGambar);
WM_COMMAND:
if(HIWORD(wParam) != BN_CLICKED)
break;
switch(LOWORD(wParam))
{
case IDB_LOAD:
BukaFormDialog(hWnd);
break;
}
break;
WM_PAINT:
PAINTSTRUCT ps ;
InvalidateRect (hWnd, NULL, TRUE);
RECT rctWindow;
GetClientRect(hWnd, &rctWindow);
RECT rctPct;
rctPct.left = 3;
rctPct.top = rctKiri.top + 3;
rctPct.right = rctKiri.right - 3;
rctPct.bottom = rctKiri.bottom- 75;
hdc = BeginPaint(hWnd, &ps);
/*------------Picture Box--------------*/
Rectangle(hdc, rctPct.left, rctPct.top, rctPct.right, rctPct.bottom);
/*-------------------------------------*/
EndPaint(hWnd, &ps);
break;
Procedure :
char BukaFormDialog(HWND hWnd)
{
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hWnd;
ofn.lpstrFilter = "File JPG (*.JPG)\0*.JPG\0File BMP (*.BMP)\0*.BMP\0File PNG(*.PNG)\0*.PNG\0All Files (*.*)\0*.*\0";
ofn.lpstrFile = szNamaFile;
ofn.lpstrTitle = "Pilih Gambar ...";
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
if(GetOpenFileName(&ofn))
{
hMem = CreateCompatibleDC(hdc);
SelectObject(hMem, hGambar);
BitBlt(hdc, 4, 4, 50,50, hMem, 0, 0, SRCCOPY);
DeleteDC(hMem);
DeleteObject(hGambar);
}
else
MessageBox(hWnd, "Gagal Membuka File", "Error", MB_ICONERROR | MB_OK);
return (0);
}
you have four problems here
1st) LoadImage(..,IMAGE_BITMAP,...) does only support BMP files.
2nd) you are deleting the wrong Handle (hGambar)
if(GetOpenFileName(&ofn))
{
hMem = CreateCompatibleDC(hdc);
hGambar=SelectObject(hMem, hGambar); //save the original hBmp
BitBlt(hdc, 4, 4, 50,50, hMem, 0, 0, SRCCOPY);
hGambar=SelectObject(hMem, hGambar); // Select Back the original hBmp
DeleteDC(hMem);
DeleteObject(hGambar); // now hGambar is back delete it
}
3rd) your above drawing is not persistent, it will be erased by any overlapping window. move it to WM_PAINT.
4th) Do not call InvalidateRect or InvalidateRgn in WM_PAINT.
here is a full working code
#include <windows.h>
HDC hdc, hdcMem;
HBITMAP hLogo, hGambar=NULL;
#ifndef IDB_LOAD
#define IDB_LOAD 1000
#endif
#define APP_CLASS TEXT("APP_CLASS")
char szNamaFile[MAX_PATH];
/*____________________________________________________________________________________________________________
*/
int BukaFormDialog(HWND hWnd)
{
OPENFILENAME ofn={sizeof(ofn)};
ofn.hwndOwner = hWnd;
ofn.lpstrFilter = "File BMP (*.BMP)\0\0";
ofn.lpstrFile = szNamaFile;
ofn.lpstrTitle = "Pilih Gambar ...";
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_FILEMUSTEXIST;
if(GetOpenFileName(&ofn))
{
HBITMAP hTmp;
DeleteObject(hGambar);
hGambar=LoadImage(NULL,szNamaFile,IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
if(hGambar){
InvalidateRect(hWnd,NULL,1);
return 1;
}
MessageBox(hWnd, "Bad Image", "Error", MB_ICONERROR | MB_OK);
}
else{
//User pressed Cancel*/;
}
return (0);
}
/*____________________________________________________________________________________________________________
*/
int WinProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam){
switch(uMsg){
case WM_CREATE:
CreateWindow(
TEXT("Button"),
TEXT("&Load"),
WS_CHILD | WS_TABSTOP | WS_VISIBLE | BS_FLAT,
149, 421, 70, 25,
hWnd, (HMENU)IDB_LOAD, NULL, NULL);
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDB_LOAD:
BukaFormDialog(hWnd);
break;
}
break;
case WM_PAINT:{
PAINTSTRUCT ps;
HDC hMem;
BeginPaint(hWnd,&ps);
if(hGambar){
if(hMem=CreateCompatibleDC(ps.hdc)){
hGambar=SelectObject(hMem,hGambar); /*select & swap*/
BitBlt(ps.hdc, 4, 4, 50,50, hMem, 0, 0, SRCCOPY);
hGambar=SelectObject(hMem,hGambar);/*select & swap back*/
DeleteDC(hMem);
}
}
EndPaint(hWnd,&ps);
}
break;
case WM_DESTROY:
DeleteObject(hGambar);
break;
default:
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
return 0;
}
/*____________________________________________________________________________________________________________
*/
int WinMain(HINSTANCE hInstance,HINSTANCE hPrev,LPSTR lpCmd,int nShow){
WNDCLASS wc={
0,
WinProc,
0,
0,
hInstance,
NULL,
LoadCursor(NULL,IDC_ARROW),
(HBRUSH) (COLOR_WINDOW+1),
NULL,
APP_CLASS};
if(RegisterClass(&wc)){
if(CreateWindow(APP_CLASS,TEXT("Title"),
WS_OVERLAPPEDWINDOW|WS_VISIBLE,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
NULL,NULL,NULL,NULL)){
MSG msg;
while(GetMessage(&msg,NULL,0,0)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
return 0;
}

Resources