How can I add LBtnMouseDown event to edit control - windows

I want when a "LBUTTONDOWN" on edit control, empty the text box.
I know how can I empty the text box , but I don't know where is the place where this event is added .
My dialog function:
INT CALLBACK dlgProc(HWND hwnd, unsigned int msg, WPARAM wp, LPARAM lp){
switch(msg){
case WM_INITDIALOG:
SetDlgItemText(hwnd, IDC_EDIT1, L"Please enter the txt");
break;
case WM_COMMAND:
switch(LOWORD(wp)){
case BTN_EXIT:
DestroyWindow(hwnd);
break;
case IDC_BUTTON1:
int len = GetWindowTextLength(GetDlgItem(hwnd,IDC_EDIT1));
if(len > 0){
TCHAR *buff = new TCHAR[len+1];
GetDlgItemText(hwnd, IDC_EDIT1, buff, len+1);
MessageBox(NULL,buff,L"Error message",MB_OK);
delete buff;
}
break;
}
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return false;
}
return true;
}

What I suspect that you really want is to respond to the control receiving input focus rather than just the button down event. For example, suppose the user uses the mouse button to set the input focus on the edit control, then types, and then clicks on the edit control again, whilst it currently has the focus. You presumably do not want the user's text to be cleared. Or perhaps they set input focus using the keyboard, e.g. TAB. Again I suspect you would want that action to clear the contents.
Assuming my understanding is correct then you should listen for the EN_SETFOCUS notification in your dialog procedure's WM_COMMAND handler. This will fire no matter how the user brings focus to the edit control, either using the mouse or by using the keyboard.
In your code you just need to expand your switch statement in the WM_COMMAND:
case IDC_EDIT1:
if(HIWORD(wParam)==EN_SETFOCUS)
{
SetDlgItemText(hwnd, IDC_EDIT1, L"");
}
break;

Related

How to capture the activation of the menubar?

I'm now trying to do some owner draw of the window frame , including the caption , the border , the mini/max/restore zone and the menubar. Escpecially for the menubar , I have done some gdi operations to redefine the area of the menubar , and repaint on WM_NCPAINT. However, when I press the Alt key or F10, the original menubar activated. I found it has something with the WM_SYSKEYDOWN , and then I blocked it. After that I put a control into the frame window, for expample, a edit control, when the control get focused, I press Alt or F10 , the original menubar of the frame window get activated again.
Wow , seems have something with the wm_notify message.
LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_NCACTIVATE:
case WM_NCPAINT: {
//NC and Menubar redrawing.
BOOL active_flag;
HDC hdc;
RECT rect={0,0,0,0};
active_flag=(BOOL)wParam;
hdc=GetWindowDC(hwnd);
Frame_NCDraw(hwnd,hdc,rect,0,&active_flag);
Frame_MenuBarDraw(hwnd,hdc);
ReleaseDC(hwnd, hdc);
return !active_flag;
} break;
case WM_INITMENUPOPUP: {
//set the background of the menu item. a little long , no source code paste.
...
//
} break;
case WM_NCHITTEST: {
// redefine the area of the HTMENU.
} break;
case WM_MEASUREITEM: {
LPMEASUREITEMSTRUCT lpmis;
lpmis = (LPMEASUREITEMSTRUCT)lParam;
//Menu item adjust the height/width.
if(lpmis->CtlType == ODT_MENU) {
UINT menu_item_id = lpmis->itemID;
lpmis->itemWidth = 200;
lpmis->itemHeight = ((menu_item_id==0x0)?5:28);
}
} break;
case WM_DRAWITEM: {
UINT ctrl_id=(UINT)wParam;
LPDRAWITEMSTRUCT pDraw=(LPDRAWITEMSTRUCT)lParam;
if(pDraw->CtlType==ODT_MENU) {
Frame_DrawMenuItem(pDraw); // MenuItem owner drawing.
}
} break;
.....
}
So How should I deal with the activation of the original menubar ? I mean , I want to forbid the painting for the original menubar. Instead , I want my MenuBar activated by the Alt or F10 key press.
In addition to the WM_SYSKEYDOWN message, you will also receive WM_SYSCOMMAND with SC_KEYMENU, you need to handle this command to activate and display your own menu.
lParam contains the character code of the key that is used with the
ALT key to display the popup menu. For example , pressing ALT+F to
display the File popup will cause a WM_SYSCOMMAND with wParam equal
to SC_KEYMENU and lParam equal to'f'.
If only ALT/F10, the test result of lParam is 0.
case WM_SYSCOMMAND:
if (wParam == SC_KEYMENU)
{
//Draw activated menubar
switch (lParam)
{
case 0:
break;
case 'f':
//pop up menu "File"
break;
case 'h':
//pop up menu "Help"
break;
default:
break;
}
return 0;
}
else
return DefWindowProc(hwnd, msg, wParam, lParam);

how to call a function on button click

I want to create two buttons that perform separate functions.
When button_B1 is clicked, Function_B1() runs.
When button_B2 is clicked, Function_B2() runs.
How do I call a function on a button click?
When a Win32 button is clicked, it sends a BN_CLICKED notification to its parent window, where the message carries the button's HWND and ID. In the parent window's wndproc, you can catch the notification and call whatever function you want for whichever button is sending the notification.
case WM_COMMAND:
{
if ((HIWORD(wParam) == BN_CLICKED) && (lParam != 0))
{
switch (LOWORD(wParam))
{
case ID_BTN1:
Function_B1();
break;
case ID_BTN2:
Function_B2();
break;
}
}
break:
}
Or
case WM_COMMAND:
{
if ((HIWORD(wParam) == BN_CLICKED) && (lParam != 0))
{
HWND hwndBtn = (HWND) lParam;
if (hwndBtn == hwndBtn1)
Function_B1();
else if (hwndBtn == hwndBtn2)
Function_B2();
}
break:
}
Thank you, Remy.
I just had a problem with the switch statement:
case WM_COMMAND:
{
switch (wmId)
{
case 1:
Function_B1(hWnd, wParam, lParam);
break;
case 2:
Function_B2(hWnd, wParam, lParam);
break;
case 3:
Function_B3(hWnd, wParam, lParam);
break;

How to cancel item label editing in Tree-View control upon ESC keydown in WinAPI

I have a dialog box with a Tree-View control where the user can edit the item labels. I want the user to be able to cancel the label edit by pressing ESC key.
The problem is that pressing ESC closes the dialog window immediately.
I have tried getting the handle to the EditBox control by a TreeView_GetEditControl() call upon TVN_BEGINLABELEDIT message and subclassing it to trap the ESC key, but when I do that, typing in edit box becomes impossible.
What is the problem?
Here is the relevant code:
INT_PTR CALLBACK DlgProc(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam) {
switch(message) {
//...
case WM_NOTIFY:
{
LPNMHDR pNmHdr = (LPNMHDR)lParam;
switch(pNmHdr->code) {
case TVN_BEGINLABELEDIT:
{
HWND hwndTV = (HWND)GetWindowLongPtr(hWnd, GWLP_USERDATA); // stored handle to Tree-View ctl
HWND hWndEditBox = TreeView_GetEditControl(hwndTV);
// subclass edit box
TreeViewGlobals::g_wpOrigEditBoxProc =
(WNDPROC)SetWindowLongPtr(hWndEditBox,
GWLP_WNDPROC, (LONG_PTR)EditBoxCtl_SubclassProc);
break;
}
case TVN_ENDLABELEDIT:
{
SetWindowLongPtr(hWnd, DWLP_MSGRESULT, (LONG)TRUE); // accept edit
return TRUE;
}
default:
break;
}
}
default:
break;
}
return FALSE;
}
INT_PTR CALLBACK EditBoxCtl_SubclassProc(HWND hWndEditBox, UINT message,
WPARAM wParam, LPARAM lParam) {
switch(message) {
HANDLE_MSG(hWndEditBox, WM_GETDLGCODE, EditBoxCtl_OnGetDlgCode);
HANDLE_MSG(hWndEditBox, WM_KEYDOWN, EditBoxCtl_OnKey); // does not receive WM_KEYDOWN for ESC unless I handle WM_GETDLGCODE above
default:
break;
}
return CallWindowProc(TreeViewGlobals::g_wpOrigEditBoxProc,
hWndEditBox, message, wParam, lParam);
}
UINT EditBoxCtl_OnGetDlgCode(HWND hWndEditBox, LPMSG lpmsg) {
if(lpmsg) {
if(lpmsg->message == WM_KEYDOWN && lpmsg->wParam == VK_ESCAPE) {
return DLGC_WANTMESSAGE;
}
}
return 0;
}
void EditBoxCtl_OnKey(HWND hWndEditBox, UINT vk, BOOL fDown,
int cRepeat, UINT flags) {
switch(vk) {
case VK_ESCAPE:
Beep(4000, 150); // never beeps
break;
default:
break;
}
}
P.S. I noticed that when I remove WM_GETDLGCODE handler in EditBoxCtl_SubclassProc(), it becomes possible to type in the edit box again, but then I can't trap WM_KEYDOWN for ESC key from that procedure.
Below is the solution that I found. The trick seems to be calling the original control proc with WM_GETDLGCODE intercepted in subclass proc, storing the return value and then returning it with DLGC_WANTALLKEYS or DLGC_WANTMESSAGE flag set to prevent system from further processing the keystroke.
The upside to this approach is that pressing ESC cancels editing and reverts the item label to its original text, and pressing ENTER while editing no longer just closes the dialog(which was another problem) without any additional code to handle those cases.
Here is the code that works:
INT_PTR CALLBACK EditBoxCtl_SubclassProc(HWND hWndEditBox, UINT message,
WPARAM wParam, LPARAM lParam) {
switch(message) {
//HANDLE_MSG(hWndEditBox, WM_GETDLGCODE, EditBoxCtl_OnGetDlgCode); // can't use this: need wParam and lParam for CallWindowProc()
case WM_GETDLGCODE: {
INT_PTR ret = CallWindowProc(TreeViewGlobals::g_wpOrigEditBoxProc,
hWndEditBox, message, wParam, lParam);
MSG* lpmsg = (MSG*)lParam;
if(lpmsg) {
if(lpmsg->message == WM_KEYDOWN &&
(lpmsg->wParam == VK_ESCAPE || lpmsg->wParam == VK_RETURN) )
{
return ret | DLGC_WANTALLKEYS;
}
}
return ret;
}
default:
break;
}
return CallWindowProc(TreeViewGlobals::g_wpOrigEditBoxProc,
hWndEditBox, message, wParam, lParam);
}
The problem is that the modal dialog has its own message loop and its own translation with IsDialogMessage. Using the MFC I would say, just use PreTranslateMessage but this isn't available in plain WinApi. You don't have access to the internal message loop and the keyboard interface.
So the Escape key is handled inside the message loop. And causes a WM_COMMAND message with IDCANCEL to be sent. (See the MSDN specs about dialogs)
Maybe the easiest way is to interrcept the WM_COMMAND message sent to the dialog, check if who has the focus and if the inplace edit control has the focus you just set the focus back to the tree control and eat forget the IDCANCEL and don't close the dialog.
you need remember the tree-view hwnd when you receive TVN_BEGINLABELEDIT (in class member, associated with dialog) and zero it when you receive TVN_ENDLABELEDIT. when user press esc or enter in modal dialog box - you receive WM_COMMAND with IDCANCEL (on esc) or IDOK( on enter). you need check saved tree-view hwnd and if it not 0 - call TreeView_EndEditLabelNow
switch (uMsg)
{
case WM_INITDIALOG:
m_hwndTV = 0;
break;
case WM_NOTIFY:
switch (reinterpret_cast<NMHDR*>(lParam)->code)
{
case TVN_BEGINLABELEDIT:
m_hwndTV = reinterpret_cast<NMHDR*>(lParam)->hwndFrom;
return TRUE;
case TVN_ENDLABELEDIT:
m_hwndTV = 0;
//set the item's label to the edited text
SetWindowLongPtrW(hwndDlg, DWLP_MSGRESULT, TRUE);
return TRUE;
}
break;
case WM_CLOSE:
EndDialog(hwndDlg, 0);
break;
case WM_COMMAND:
switch (wParam)
{
case IDCANCEL:
if (m_hwndTV)
{
TreeView_EndEditLabelNow(m_hwndTV, TRUE);
}
else
{
EndDialog(hwndDlg, IDCANCEL);
}
break;
case IDOK:
if (m_hwndTV)
{
TreeView_EndEditLabelNow(m_hwndTV, FALSE);
}
else
{
EndDialog(hwndDlg, IDOK);
}
break;
}
break;
}

infinite loop inside the getmessage (DispatchMessage(& msg ); is not working)

I am creating a button application using resource editor. After creating button I try to do like this-
m_hwndPreview = CreateDialogParam( g_hInst,MAKEINTRESOURCE(IDD_MAINDIALOG), m_hwndParent,(DLGPROC)DialogProc, (LPARAM)this);
if (m_hwndPreview == NULL)
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
MSG msg;
BOOL bRet;
while ( (bRet=GetMessage (& msg,0, 0,0)) != 0)
{// this msg always contains the data like -msg = {msg=0x0000c03e wp=0x0000000000000012//always 12 I don't know why ?? lp=0x0000000000000000}
if (bRet == -1)
{
bRet = HRESULT_FROM_WIN32(GetLastError());
MessageBox(NULL, L"Hurr i am the error",L"Error",MB_ICONERROR | MB_OK);
}
else if (!IsDialogMessage (m_hwndPreview, & msg))
{
TranslateMessage (&msg); //on debugging TranslateMessage = 0x000007feee615480 TranslateMessage
DispatchMessage(& msg ); //but show nothing when I put cursor on this method to know the value that means it's not called
MessageBox(NULL, L"there is no error in receiving before dispatch the message",L"Error",
MB_ICONERROR | MB_OK);//this messagebox repeats again and again after the call to DialogProc function and I am not able to come out of the loop and here I need to restart my PC
at some other place I define createdialog function like this-
//this function is called just on createDialogParam() function.after it the controls go to getmessage where everything loops.
BOOL CALLBACK AMEPreviewHandler::DialogProc(HWND m_hwndPreview, UINT Umsg, WPARAM wParam, LPARAM lParam)
{ //this dialogProc function is declares Static some where in the code otherwise the createdialogparam will give error DLGPROC is invalid conversion
//this Umsg alays creates strange value like 48 and 32 etc.. and Wparam contains a very big value like 12335423526 (I mean big and strange) and lparam contains 0.
switch(Umsg)
{
case WM_INITDIALOG:
{
MessageBox(NULL, L"Inside the WM_INITDIALOG function",L"Error",
MB_ICONERROR | MB_OK);
return TRUE;
}
break;
case WM_CREATE:
{
/////////////////
MessageBox(NULL, L"Inside the WM_CREATE",L"Error",
MB_ICONERROR | MB_OK);
/////////////////////////////////
}
break;
case WM_COMMAND:
{ //here are my two buttons created by me which should show messagebox on click
int ctl = LOWORD(wParam);
int event = HIWORD(wParam);//I don't know why this event is in blue colour .. but its not the pqrt of problem right now.
if (ctl == IDC_PREVIOUS && event == BN_CLICKED )
{
MessageBox(m_hwndPreview,L"Button Clicked is next inside WM_COMMAND ",L"BTN WND",MB_ICONINFORMATION);
return 0;
}
if (ctl == IDC_NEXT && event == BN_CLICKED )
{
MessageBox(m_hwndPreview,L"Button Clicked is previous inside WM_COMMAND",L"BTN WND",MB_ICONINFORMATION);
return 0;
}
return FALSE;
}break;
case WM_DESTROY:
{
////////////////::
MessageBox(NULL, L"Inside the WM_DESTROY",L"Error",
MB_ICONERROR | MB_OK);
//////////////////
PostQuitMessage(0);
return 0;
}
break;
case WM_CLOSE:
{
MessageBox(NULL, L"Inside the WM_CLOSE",L"Error",
MB_ICONERROR | MB_OK);
DestroyWindow (m_hwndPreview);
return TRUE;
}
break;
}
MessageBox(NULL, L"outside the DefWindowProc function",L"Error",
MB_ICONERROR | MB_OK);
return 0;
}
The problem occurring is that when I debut it the control first go to CreateDialogParam and then it go to getmessage where the control don't come out of the loop causing restart problem. And I have no display of button and image at preview pane. What I expect if everything go fine is after debugging it should show picture on preview pane and I have 2 buttons "Next" and "Previous" but it show just a blank window (the buttons and photo I have already created using Resource editor... That's correct I am sure about that) .. but I don't know why I am not coming out getmessage function and dispatchmessage is not called (because I saw on debugging).
so now you can try to comment the getmessage part code that will probably out if the problem because you are creating button using IDD_MAINDIALOG and your createdialogparam directly calls your dailogproc function where you receive WM_COMMAND and that you handle by your code behind.
you should write
return true;
just after the DispatchMessage(msg);
and tehn debug it and inform me about t he result on debugging.

How to close dialogbox(Child) without close the Main dialog(parent)

I have one parent dialog , this dialog have menu , in this menu (Help->about).
when I click on the about selection, show about DialogBox.
I want if I click on Ok or close(X) button, close this dialog box only not the main dialog box.
This my attempts:
// ------------- Main dialog function
BOOL CALLBACK DlgFunc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp){
switch(msg){
case WM_COMMAND:
switch(LOWORD(wp)){
case IDM_HABOUT: // Here, I set when I click on help selection in the menu creates (about dialogbox)
DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_AboutDlg), hwnd, AboutDlgFunc);
break;
}
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return false;
}
return true;
}
// ------------- About dialog function
BOOL CALLBACK AboutDlgFunc(HWND HabutWnd, UINT msg, WPARAM wp, LPARAM lp){
switch(msg){
case WM_COMMAND:
if(LOWORD(wp) == IDOK)
EndDialog(HabutWnd,0);
break;
case WM_CLOSE:
EndDialog(HabutWnd,0);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return false;
}
return true;
}
Don't call PostQuitMessage in WM_DESTROY inside AboutDlgFunc. This essentially causes the entire program to quit.

Resources