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.
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;
}
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;
}
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).
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;
}