win32 select all on edit ctrl (textbox) - c++

I am creating my textbox with these options. I can Copy / Cut / Paste / Undo, but when I hit Select All it doesn't select all. I can right click and click Select All but CTRL + A doesn't do anything. Why?
wnd = CreateWindow("EDIT", 0,
WS_CHILD | WS_VISIBLE | ES_MULTILINE | WS_HSCROLL | WS_VSCROLL | ES_AUTOHSCROLL | ES_AUTOVSCROLL,
x, y, w, h,
parentWnd,
NULL, NULL, NULL);

Ctrl+A is not a built-in accelerator like Ctrl+C and Ctrl+V. This is why you see WM_CUT, WM_PASTE and WM_COPY messages defined, but there is no WM_SELECTALL.
You have to implement this functionality yourself. I did in my MFC app like this:
static BOOL IsEdit( CWnd *pWnd )
{
if ( ! pWnd ) return FALSE ;
HWND hWnd = pWnd->GetSafeHwnd();
if (hWnd == NULL)
return FALSE;
TCHAR szClassName[6];
return ::GetClassName(hWnd, szClassName, 6) &&
_tcsicmp(szClassName, _T("Edit")) == 0;
}
BOOL LogWindowDlg::PreTranslateMessage(MSG* pMsg)
{
if(pMsg->message==WM_KEYDOWN)
{
if ( pMsg->wParam=='A' && GetKeyState(VK_CONTROL)<0 )
{
// User pressed Ctrl-A. Let's select-all
CWnd * wnd = GetFocus() ;
if ( wnd && IsEdit(wnd) )
((CEdit *)wnd)->SetSel(0,-1) ;
}
}
return CDialog::PreTranslateMessage(pMsg);
}
Note, I stole IsEdit from this page: http://support.microsoft.com/kb/145616
I point that out partly because I want to give credit, and partly because I think the IsEdit function (comparing classname strings) is dorky and I want to give blame.

You could simply use EM_SETSEL message to the textbox,
According to MSDN ,
If the start is 0 and the end is –1, all the text in the edit control is selected. If the start is –1, any current selection is deselected.
so,
SendMessage(hwndEdit,EM_SETSEL,0,-1);
Will work fine.

I tend to use MFC (forgive me) instead of Win32 so I cannot answer this definitively, but I noticed this comment added to a page on an MS site concerning talking with an Edit control (a simple editor within the Edit control):
The edit control uses WM_CHAR for
accepting characters, not WM_KEYDOWN
etc. You must Translate() your
messages or you ironically won't be
able to edit the text in the edit
control.
I don't know if this applies to BoltBait's response, but I suspect it does.
(I found this at http://msdn.microsoft.com/en-us/library/bb775462(VS.85).aspx)

You need to capture that keystroke and do the select all yourself.
Here is some C# code for use with a RichTextBox:
protected override void OnKeyDown(KeyEventArgs e)
{
// Ctrl-A does a Select All in the editor window
if (e.Control && (e.KeyCode == Keys.A))
{
this.SelectAll();
e.Handled = true;
}
}
Sorry, I don't have Win32 code for you.

The strange thing is that Ctrl+A DOES work (as select all), if you do NOT specify ES_MULTILINE
But that doesn't help if you need multiline
The MSDN documentation for ES_MULTILINE doesn't appear to say anything about this.

Could it be that something else is stealing Ctrl+A? Use Spy++ to verify that it reaches your edit control.

Why not add an accelerator for Ctrl+a to SelectAll?

Related

unable to set focus to CEdit control

I encounter a problem with CEdit textbox , the exact problem is that i unable to Set Focus to the control after creating it.
What i want to do is:
Create CEdit control temporary.
Set focus to the control.
Get the number from the control and store it in a value.
Destroy control after 10 second.
After some research on internet i couldn’t find solution to the problem , therefore i address to you.
Hope to find a solution. Thanks in advance.
i tried
editctrl.SetFocus();
DWORD dw = LOWORD(editctrl.GetDlgCtrlID()) | HIWORD(EN_SETFOCUS);
SendMessage(WM_COMMAND,(WPARAM)dw, (LPARAM)editctrl.GetHandle());
BOOL CViewsDlg::PreTranslateMessage(MSG* pMsg)
{
// TODO: Add your specialized code here and/or call the base class
if (pMsg->message == WM_KEYDOWN && pMsg->wParam == 0xBB /*+*/)
{
if (!editctrl)
{
editctrl.Create(ES_NUMBER | WS_CHILD|WS_VISIBLE | WS_BORDER | WS_TABSTOP, CRect(0, 0, 100, 20), this, NULL);
editctrl.ShowWindow(SW_SHOW);
editctrl.SetFocus();
//DWORD dw = LOWORD(editctrl.GetDlgCtrlID()) | HIWORD(EN_SETFOCUS);
//SendMessage(WM_COMMAND,(WPARAM)dw, (LPARAM)editctrl.GetHandle());
telestis = e_sinplin;
SetTimer(1, 10000, NULL);
}
}
return CDialogEx::PreTranslateMessage(pMsg);
}
You need to use CDialog::GotoDlgCtrl to set focus in dialog windows.

MFC redirect/catching MESSAGE_MAP | PreTranslateMessage?

I have a problem using MESSAGE_MAP &/or PreTranslateMessage. This may be a design issue but I'm not sure. The main issue is MESSAGE_MAP code not being called & not sure how to do same via PreTranslateMessage. ie as follows:
//MyCDialogEx : public CDialogEx
class MyCDialogEx::Init()
{
CFlatSplitterWnd m_cSplitter; //http://www.codersource.net/2010/01/29/mfc-splitter-window/
m_pFrame = new CFlatFrameWnd;
m_pFrame->Create(strMyClass, L"", WS_CHILD, rect, this);
m_pFrame->ShowWindow(SW_SHOW);
m_cSplitter.CreateStatic(m_pFrame, 1, 2);
m_cSplitter.ModifyStyleEx(WS_EX_CLIENTEDGE, 0, SWP_NOSIZE | SWP_NOACTIVATE);
m_cSplitter.CreateView(0, 0, RUNTIME_CLASS(CHolderView), CSize(100, 100), &ccc);
CHolderView* pView = (CHolderView*)m_cSplitter.GetPane(0, 0);
ASSERT_VALID(pView);
pView->setWnd(&m_TreeCtrl);
pView->setOwner(this, IDC_TREECTRL);
const DWORD dwStyle = LBS_NOTIFY | WS_CHILD | WS_VISIBLE | TVS_HASBUTTONS | TVS_HASLINES
| TVS_LINESATROOT | TVS_CHECKBOXES | TVS_SHOWSELALWAYS | WS_BORDER | WS_HSCROLL | WS_TABSTOP;
m_TreeCtrl.Create(dwStyle, CRect(0, 0, 1, 1), pView, IDC_TREECTRL);
}
BEGIN_MESSAGE_MAP(MyCDialogEx, CDialogEx)
ON_NOTIFY_REFLECT(WM_ONMYCLICK, OnClickTreectrl) //this & following not called
ON_NOTIFY(NM_CLICK, IDC_TREECTRL, OnClickTreectrl)
ON_NOTIFY(TVN_ITEMCHANGED, IDC_TREECTRL, OnItemchangedTreectrl)
ON_NOTIFY(TVN_SELCHANGED, IDC_TREECTRL, OnSelchangedTreectrl)
ON_NOTIFY(TVN_KEYDOWN, IDC_TREECTRL, OnKeydownTreectrl)
END_MESSAGE_MAP()
BOOL MyCDialogEx::PreTranslateMessage(MSG* pMsg)
{
if (GetFocus() && GetFocus()->GetDlgCtrlID() == IDC_TREECTRL)
{
//what/how goes in here to catch NM_CLICK, TVN_ITEMCHANGED etc??
if (pMsg->message == WM_LBUTTONDOWN)
{
switch (LOWORD(pMsg->wParam))
{
case NM_CLICK:
break;
}
}
if (pMsg->message == WM_KEYDOWN)
TRACE(L"WM_KEYDOWN\n");
if (pMsg->message == WM_KEYUP)
TRACE(L"WM_KEYUP\n");
}
return MyCDialogEx::PreTranslateMessage(pMsg);
}
void MyCDialogEx::OnClickTreectrl(NMHDR *pNMHDR, LRESULT *pResult) //not called
{
TRACE(L"tree click\n");
*pResult = 0;
}
MESSAGE_MAP works if I house these in CHolderView class MESSAGE_MAP, but I rather not as it's just a container class & will possibly be used elsewhere in my project.
What I'd really like to do is use MESSAGE_MAP to minimize coding via PreTranslateMessage (& if it's possible to redirect to MESSAGE_MAP, how?). If I must resort to PreTranslateMessage or other, then how do I use this so I can catch the relevant NM_CLICK, TVN_ITEMCHANGED for tree control etc.
Thank you.
EDIT: oh & the following don't help, not relevant or don't sufficiently explain:
How to get Click Event of Treeview(CTreeCtrl) in MFC created at runtime?
How to redirect MFC messages to another object?
How can identify Mouse Click event in PreTranslateMessage?
The problem is that the tree view will send all its notifications to the parent window. And the parent windows is the CHolderWindow.
Messages are not routed like WM_COMMAND messages. So handler for WM_COMMAND messages may reside anywhere in the notification path.
But regular window control notifications are always handled in the direct parent of the window. In MFC you can redirect such notfications to the child window control itself. Using ON_..._REFLECT.
A trick can be: Set a pointer to a window to the holder window, that should receive all messages. Than accept all WM_COMMAND and all WM_NOTIFY messages in the holder window and resend them to the new window.
PreTranslateMessage is another thing. The target window always receives a call first. Than all parents will get a chance until somebody in the chain of PreTranslateMessage calls returns TRUE.

Common Dialogboxes Win32

I have a common color dialog box that I want to activate on a menu press.
Unfortunately, every time I press on the item, the window loses focus, as if a dialog box is coming up, but the dialog box never shows up.
The code I'm using right now is below:
case ID_TOOL_CHOOSECOLOR:
//show colour dialog
ChooseColor(&cc);
and I've initialized my CHOOSECOLOR structure like this:
cc.lStructSize = sizeof (CHOOSECOLOR) ;
cc.hwndOwner = NULL ;
cc.hInstance = NULL ;
cc.rgbResult = RGB (0x80, 0x80, 0x80) ;
cc.lpCustColors = crCustColor ;
cc.Flags = CC_RGBINIT | CC_FULLOPEN ;
cc.lCustData = 0 ;
cc.lpfnHook = NULL ;
cc.lpTemplateName = NULL ;
What's weird is, the dialog box only shows up after I press the "ALT" key (and only the alt key). Any tips?
I'm trying to do this in an MDI document by the way.
Thanks
The only problem I can see is that you did not specify an owner for the dialog. This could lead to the dialog showing behind your main window. Specify the handle of your main window to be the dialog's owner.
Read more about window ownership on the Window Features page on MSDN.
Fixed it!
Turns out, the issue I had was in the main window's WndProc.
I had set my WM_PAINT command to return 0; instead of break;.
Changing my return 0 to break solved everything!
I think this is cause my return would exit the wndproc, whereas break would allow me to continue to the return MDIFrameProc(hwnd, message, wparam, lparam) .
I maybe wrong, but that's the best explanation that I can come up with that explains why break works but return 0 doesn't.
After you paint, make sure you call ValidateRect(HWND,CONST RECT*);
// https://learn.microsoft.com/en-us/windows/win32/dlgbox/color-dialog-box
// http://winapi.freetechsecrets.com/win32/WIN32Choosing_a_Color.htm
COLORREF acrCustClr[16]; // array of custom colors
CHOOSECOLOR cc = {sizeof(cc)};
ZeroMemory(&cc, sizeof(CHOOSECOLOR));
cc.lStructSize = sizeof(CHOOSECOLOR);
cc.hwndOwner = hwnd;
cc.Flags = CC_FULLOPEN | CC_RGBINIT;
cc.lpCustColors = (LPDWORD) acrCustClr;
BOOL fOk = ChooseColor(&cc);
if (fOk) {
}

DialogBoxIndirect creates dialog bigger than asked

For my application I need to create a Dialog Box without using resource.
I am trying to do it with DialogBoxInderect function.
The code is unbelievably ugly but somehow I succeeded to do it.
The problem is that dialog, for some reason, is much bigger than I asked with much bigger fonts.
Here is how the dialog looks like if I load it from resource:
And here is the dialog with the same size stated when I call DialogBoxInderect function.
Here is how it is defined in code:
HGLOBAL hGlobal;
LPDLGTEMPLATE wlsDialogTemplate;
LPDLGITEMTEMPLATE wlsDialogItemTemplate;
LPWORD nextItem;
LPWSTR itemString;
int32_t itemStringLength;
// Check for memory allocation errors
hGlobal = GlobalAlloc(GMEM_ZEROINIT, 1024);
if (!hGlobal)
return -1;
wlsDialogTemplate = (LPDLGTEMPLATE)GlobalLock(hGlobal);
// Define a dialog box.
wlsDialogTemplate->style = WS_CAPTION;
wlsDialogTemplate->x = 0;
wlsDialogTemplate->y = 0;
wlsDialogTemplate->cx = 320;
wlsDialogTemplate->cy = 115;
GlobalUnlock(hGlobal);
retCode = DialogBoxIndirect(0, (LPDLGTEMPLATE)hGlobal, 0, ActivateWlsMsgDialog);
And here is how it is defined in RC file:
IDD_WLS_SMALL_MESSAGE_DLG DIALOGEX 0, 0, 320, 115
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION
CAPTION "Dialog"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",ID_CUSTOM_OK,175,95,120,15
PUSHBUTTON "Cancel",ID_CUSTOM_CANCEL,45,95,120,15
CTEXT "Static",IDC_HEADER_TEXT,120,10,170,70
CONTROL "",IDC_LOGO,"Static",SS_BITMAP,16,10,83,70
END
As you can see, the second dialog is much bigger than defined. I tried to play with various style flags but without any success (That is why there is red cross on the bigger dialog).
Any help with that?
Thanks!
The larger size is easy to explain. Windows automatically sizes the dialog in accordance with its font, and the larger dialog uses a different font. In fact, it is using the default system font (more info on the confusing issue of Windows dialog fonts is found in my answer here).
So the real issue to focus on is why it's using a different font, and fixing that will solve the size problem.
In the dialog box resource file, you specify the DS_SETFONT flag as one of the dialog box styles. According to the documentation, this flag
[i]ndicates that the header of the dialog box template (either standard or extended) contains additional data specifying the font to use for text in the client area and controls of the dialog box. If possible, the system selects a font according to the specified font data. The system passes a handle to the font to the dialog box and to each control by sending them the WM_SETFONT message.
So that explains why that one is displaying with the expected font.
The next logical question is what's different about your dynamically-created dialog template, shown with the DialogBoxIndirect function. The culprit is, once again, the DS_SETFONT flag, but in this case, the flag is absent. That means that the dialog doesn't contain any information about which font to use to display its controls, and the system defaults to the default system font (which is the ugly Windows 2.0-era font that you see in the second screenshot).
Once we've come to this understanding, the solution should be obvious: you need to tell the dialog which font you want it to use. There are two possible ways of doing so that come to mind:
You can set the DS_SETFONT flag and provide the font information in the header of the dialog box template as described in the above-linked documentation.
Or you can simply create and set the dialog's font in response to the WM_INITDIALOG message.
The latter is probably what you really want to do, as it allows you to use the actual system font (which, confusingly, is different from what I've been calling the "default" system font), which is Segoe UI in Windows Vista and later. Note that even in your first screenshot, it's using MS Sans Serif and therefore sticks out like a sore thumb in the Aero interface. Again, see this answer for more about fonts than you ever wanted to know and sample code for making this work. You'll need to make sure that you set the font for the dialog itself and all of its child controls.
I had played with DialogBoxIndirect (actually with DialogBoxIndirectParam), and here's the part of the code that sets the font. Observe the DS_SHELLFONT option.
LPWORD lpwAlign(LPWORD lpIn, int nAlignment)
{
return (LPWORD)(((ULONG_PTR)lpIn + nAlignment - 1) & -nAlignment);
}
LRESULT DisplayMyMessage(HINSTANCE hinst, HWND hwndOwner, LPMYMESSAGEPARAMS pParams)
{
WORD mem[1024]; // Buffer for dialog resource
LPDLGTEMPLATEW lpdt; // Pointer to heading resource structure
LPDLGITEMTEMPLATEW lpdit; // Pointer to current control
LPWORD lpw; // Cursor to resource buffer
LPWSTR lpwsz; // Cursor to resource buffer (of type WCHAR)
LPCWSTR lpwszCaption; // Aux pointer for text copying
LRESULT ret; // Function's return value
lpdt = (LPDLGTEMPLATEW)lpwAlign( mem, 4 );
//-----------------------
// Define a dialog box.
//-----------------------
lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU | WS_CAPTION |
DS_MODALFRAME | DS_CENTER | DS_SHELLFONT;
lpdt->dwExtendedStyle = 0;
lpdt->cdit = 3; // number of controls
lpdt->x = 0; lpdt->y = 0;
lpdt->cx = 164; lpdt->cy = 49;
lpw = (LPWORD)(lpdt + 1);
// Dialog menu
*lpw++ = 0;
// Dialog class
*lpw++ = 0;
// Dialog title
for (lpwsz = (LPWSTR)lpw, lpwszCaption = L"Choose language";
*lpwsz++ = *lpwszCaption++;
);
lpw = (LPWORD)lpwsz;
// Dialog font
if ( lpdt->style & (DS_SETFONT | DS_SHELLFONT) )
{
// Size
*lpw++ = 8;
// Typeface name
for (lpwsz = (LPWSTR)lpw, lpwszCaption = L"MS Shell Dlg";
*lpwsz++ = *lpwszCaption++;
);
lpw = (LPWORD)lpwsz;
}
// Define the rest of the controls
...
ret = DialogBoxIndirectParamW( hinst, lpdt,
hwndOwner, MyMessageProc, (LPARAM)pParams );
return ret;
}
This can be solved in your dialog handler by looking for the WM_INITDIALOG message, and then setting the font for all the controls in the dialog.
int CALLBACK SetChildFont(HWND child, LPARAM font) {
SendMessage(child, WM_SETFONT, font, TRUE);
return TRUE;
}
static int CALLBACK MyMessageProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_INITDIALOG:
/* Set font for dialog and all child controls */
EnumChildWindows(hwnd, (WNDENUMPROC)SetChildFont, (LPARAM)GetStockObject(DEFAULT_GUI_FONT));
break;
}
return 0;
}

ownerdrawn checkbox

i have a native win32 c++ application which has a checkbox in it. I want to replace the checkbox and create ON/OFF toggle button with 2 states (just like the checkbox). I've added the BS_OWNERDRAW style to the checkbox and drawn it to the window in WM_DRAWITEM. The problem is that when I click on the checkbox I get a WM_COMMAND message (just like without the BS_OWNERDRAW) but the CHECKED state doesn't change automaticly. Do I have to implement this functionality or am I missing something?
The code that handles clicking on the checkbox:
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
switch (wmId)
{
case IDC_CHECKBOX:
if(wmEvent == BN_CLICKED)
{
dwPos = SendMessage(checkBox, BM_GETCHECK, 0, 0);
if(dwPos == BST_CHECKED )
{
// do some stuff
} else if(dwPos == BST_UNCHECKED) {
// do some stuff
}
}
The problem is that every time i click on the checkbox BM_GETCHECK returns BST_UNCHECKED. If i remove the BS_OWNERDRAW it works fine.
Code that creates the button/checkbox:
checkBox = CreateWindowEx(
0,
WC_BUTTON,
szBuffer,
WS_VISIBLE | WS_CHILD | BS_AUTOCHECKBOX | BS_OWNERDRAW,
BUTTON_ON_OFF_X, BUTTON_ON_OFF_Y,
BUTTON_ON_OFF_WIDTH, BUTTON_ON_OFF_HEIGHT,
hWnd,
(HMENU)IDC_CHECKBOX,
hInst,
NULL
);
Ordinarily, you would set BS_AUTOCHECKBOX to have the checkbox check/uncheck automatically in response to user input. However, according to the docs, you cannot combine other styles (e.g., BS_AUTOCHECKBOX) when using BS_OWNERDRAW.
http://msdn.microsoft.com/en-us/library/windows/desktop/bb775951%28v=vs.85%29.aspx
Yes. You will need to translate from your WM_COMMAND and toggle the internal check state with something like CheckDlgButton.