Modifying menu items - c++

I have a popup menu I would like to modify before it is being displayed. I can actually modify the string of a menu item fine. The problem is, that this renders it useless as nothing happens when the modified menu item is clicked on.
CMenu* pPopup = menu.GetSubMenu(0);
ASSERT(pPopup != NULL);
CWnd* pWndPopupOwner = this;
while(pWndPopupOwner->GetStyle() & WS_CHILD)
pWndPopupOwner = pWndPopupOwner->GetParent();
// modify string
pPopup->ModifyMenu(1, MF_BYPOSITION | MF_STRING, NULL, oss.str().c_str());
pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, pWndPopupOwner);

Your call to ModifyMenu is setting the menu's ID to zero (via the third argument). You need to keep that ID the same.
If that's awkward, the SetMenuItemInfo API lets you change the string without changing the ID.

Related

Add Window Close Button To Menu Bar -- C++

I am trying to write an application that does not have a title/caption bar (a gross waste of screen real estate). So, I wish to add a close button ("X") to the end of the menu bar. Here is the code that I have tried:
mII.cbSize = sizeof(MENUITEMINFO);
mII.fMask = MIIM_FTYPE | MIIM_BITMAP;
mII.fType = MFT_BITMAP | MFT_RIGHTJUSTIFY;
mII.hbmpItem = HBMMENU_MBAR_CLOSE;
InsertMenuItem(hMenu, NUMMI, TRUE, &mII);
DrawMenuBar(hwnd);
In this case, "NUMMI" is equal to 5, the current number of main-menu items (numbered '0' through '4'). The new close button would be item number '5'.
However, the code seems to do nothing! No button appears on the menu bar. Am I missing something?
Thanks Remy. I eliminated the MFT_BITMAP flag, and now, it works. The MS documentation did not make this clear.
For those who might be reading this, asking the same question, I should note, that the above code only displays the button. Functionality must be added, just like any other button or menu item. A unique identifier is assigned to the wID member of the structure. The command is handled in the WM_COMMAND case, along with the other menu items.
Here is the revised, working code:
mII.cbSize = sizeof(MENUITEMINFO);
mII.fMask = MIIM_FTYPE | MIIM_BITMAP;
mII.fType = MFT_RIGHTJUSTIFY;
mII.wID = ID_MENUBAR_CLOSE;
mII.hbmpItem = HBMMENU_MBAR_CLOSE;
InsertMenuItem(hMenu, NUMMI, TRUE, &mII);
DrawMenuBar(hwnd);
ID_MENUBAR_CLOSE is a macro, defining a unique number that I assigned to this button. The command is the handled in the WM_COMMAND case:
case ID_MENUBAR_CLOSE:
SendMessage(hwnd, WM_CLOSE, 0, 0L); return 0;
return 0;
Voila, a working close button on the menu bar.

Is it not possible to add our own menu items on the CHtmlView context menu?

So I keep coming back to this article on CodeProject:
https://www.codeproject.com/Articles/4758/How-to-customize-the-context-menus-of-a-WebBrowser
I then realised this statement at the top of the article:
The revised sample projects are using a new, much better customization approach that is going to be comprehensively discussed in the next update of this article, which will hopefully be ready in a couple of weeks. I am publishing this semi-documented and not fully-tested code, because I am having indications that some developers may need to have this code much sooner than the day of my next update. For each revised sample there is also a Readme.htm file that briefly describes how the sample works.
I thought I was struggling to understand the code in the article snippets vs the downloaded source! So I read the readme and it stated:
In MFC 7 CHtmlView has embedded support for IDocHostUIHandler, thus I simply override the CHtmlView::OnShowContextMenu method and afterwards I call the ::CustomShowContextMenu() function, (inside CustomMenus.cpp) which works like described in the section 5 of my original article.
So, I decided to add my own function override in my project:
HRESULT CChristianLifeMinistryHtmlView::OnShowContextMenu(DWORD dwID, LPPOINT ppt,
LPUNKNOWN pcmdtReserved, LPDISPATCH pdispReserved)
{
return CustomContextMenu(ppt, pcmdtReserved);
}
And I added the similar custom menu function:
HRESULT CustomContextMenu(POINT* ppt, IUnknown* pcmdtReserved)
{
IOleWindow* oleWnd = NULL;
HWND hwnd = NULL;
HMENU hMainMenu = NULL;
HMENU hPopupMenu = NULL;
HRESULT hr = 0;
INT iSelection = 0;
if ((ppt == NULL) || (pcmdtReserved == NULL))
goto error;
hr = pcmdtReserved->QueryInterface(IID_IOleWindow, (void**)&oleWnd);
if ((hr != S_OK) || (oleWnd == NULL))
goto error;
hr = oleWnd->GetWindow(&hwnd);
if ((hr != S_OK) || (hwnd == NULL))
goto error;
hMainMenu = LoadMenu(AfxGetInstanceHandle(),
MAKEINTRESOURCE(IDR_MENU_HTML_POPUP));
if (hMainMenu == NULL)
goto error;
hPopupMenu = GetSubMenu(hMainMenu, 0);
if (hPopupMenu == NULL)
goto error;
// Show shortcut menu
iSelection = ::TrackPopupMenu(hPopupMenu,
TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD,
ppt->x,
ppt->y,
0,
hwnd,
(RECT*)NULL);
// Send selected shortcut menu item command to shell
if (iSelection != 0)
(void) ::SendMessage(hwnd, WM_COMMAND, iSelection, NULL);
error:
if (hMainMenu != NULL)
::DestroyMenu(hMainMenu);
return S_OK;
}
Finally, I added a menu resource:
IDR_MENU_HTML_POPUP MENU
BEGIN
POPUP "CustomPopup"
BEGIN
MENUITEM "View Source", 2139
MENUITEM SEPARATOR
MENUITEM "Select All", 31
END
END
The menu ID values are based on the IDM_ versions and they all work.
I then tried to add my own menu item into that list with my own event handler and it shows as disabled.
Is it not possible to add our own menu items on the CHtmlView context menu?
I wanted to add my own menu item "Print Preview" which in turn simply posted a message to my parent "Editor" to simulate clicking "Print Preview" there. But it seems that any custom item that is added to this menu is always greyed out.
If I add a "Print Preview" menu item and give it a value of 2003(IDM_PRINTPREVIEW) it just triggers the original print preview mechanism. And I can't add my own event handler for the same to my CChristianLifeMinistryHtmlView class as it is not honoured.
I found this article which mentions:
Should you choose to replace the standard menu with your own, you can
still append menu extensions to your custom menu. Simply include a
blank IDM_MENUEXT_PLACEHOLDER menu option in your menu definition to
indicate where the custom commands are to be inserted. Menu extensions
are inserted just before this placeholder. You can also add your own
custom command to the standard menu by inserting the menu option
before IDM_MENUEXT_PLACEHOLDER, as shown in the following example.
#define IDM_MENUEXT_PLACEHOLDER 6047
// If the placeholder is gone or was never there, then just exit if
(GetMenuState(hMenu, IDM_MENUEXT_PLACEHOLDER, MF_BYCOMMAND) != (UINT)
-1) { InsertMenu(hMenu, // The Context Menu
IDM_MENUEXT_PLACEHOLDER, // The item to insert before
MF_BYCOMMAND|MF_STRING, // by item ID and str value
IDM_MENUEXT_FIRST__ + nExtCur, // the command ID
(LPTSTR)aOpts[nExtCur].pstrText);// The menu command text
// Remove placeholder DeleteMenu(hMenu, IDM_MENUEXT_PLACEHOLDER,
MF_BYCOMMAND); }
The menu IDs for extensions fall between IDM_MENUEXT_FIRST__ and IDM_MENUEXT_LAST__ for a maximum of 33 custom
commands.
I know I didn't design it right but I added a menu item for the place holder and then another for Print Preview with a menu item id of IDM_MENUEXT_FIRST__. I then added a menu handler to it. The menu item is no longer disabled so that is good. But clicking it does nothing.
This question relates to:
CHtmlView and Print Preview and Context menu
Update
I think I have found a solution and will provide an answer shortly.
I have got to the bottom of this. There were a few key things that I learned along the way.
Concept 1
I was not away of the CHtmlView::OnShowContextMenu function which I needed to implement:
HRESULT CChristianLifeMinistryHtmlView::OnShowContextMenu(DWORD dwID, LPPOINT ppt,
LPUNKNOWN pcmdtReserved, LPDISPATCH pdispReserved)
{
return CustomContextMenu(ppt, pcmdtReserved);
}
In my defence, the IDE in Visual Studio did not offer it in the list as a possibly override. But it existed non-the-less.
Concept 2
The menu IDs for all custom menu items fall between IDM_MENUEXT_FIRST__ and IDM_MENUEXT_LAST__ for a maximum of 33 custom commands. In my case I manually create some #define values in my resource.h file:
#define CUSTOM_MENU_PRINT_PREVIEW 3700
#define CUSTOM_MENU_EXPORT 3701
Note that I am not happy using literal values. I wish I could use IDM_MENU_EXT_FIRST + 1 etc. for my definitions but I do not know how to do that. Possible?
Concept 3
When you design your custom menu you can infill existing commands with the IDM_XXX values too:
IDR_MENU_HTML_POPUP MENU
BEGIN
POPUP "CustomPopup"
BEGIN
MENUITEM "Select All", 31
MENUITEM SEPARATOR
MENUITEM "Export", CUSTOM_MENU_EXPORT
MENUITEM SEPARATOR
MENUITEM "Page Setup", 2004
MENUITEM "Print Preview", CUSTOM_MENU_PRINT_PREVIEW
MENUITEM SEPARATOR
MENUITEM "Refresh", 2300
MENUITEM SEPARATOR
MENUITEM "View Source", 2139
END
END
The same note still applies though. I can't work out how to assign the IDM_* constants to my own #defines rather than using literal values.
Your custom menu items will be greyed out if you don't use the right ID values.
Concept 4
Then you have to create the context menu (see original question for that code).
Concept 5
This is closely related to item 4. TrackMenuPopup needed to be adjusted in my situation as follows:
// Show shortcut menu
iSelection = ::TrackPopupMenu(hPopupMenu,
TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD,
ppt->x,
ppt->y,
0,
hwnd,
(RECT*)NULL);
// Send selected shortcut menu item command to shell
if (iSelection != 0)
{
if (iSelection == CUSTOM_MENU_PRINT_PREVIEW)
{
::SendMessage(GetParent()->GetSafeHwnd(), WM_COMMAND, ID_FILE_PRINTPREVIEW, NULL);
}
else if (iSelection == CUSTOM_MENU_EXPORT)
{
::SendMessage(GetParent()->GetSafeHwnd(), WM_COMMAND, ID_FILE_EXPORT, NULL);
}
else
{
(void) ::SendMessage(hwnd, WM_COMMAND, iSelection, NULL);
}
}
The key was testing the return value of TrackMenuPopup and doing custom handling. In-fact, whilst writing this answer I now realise that my "Print Preview" menu item can be defined as the value of IDM_PRINTPREVIEW and I test again that, like this:
if (iSelection != 0)
{
if (iSelection == IDM_PRINTPREVIEW)
{
::SendMessage(GetParent()->GetSafeHwnd(), WM_COMMAND, ID_FILE_PRINTPREVIEW, NULL);
}
else if (iSelection == CUSTOM_MENU_EXPORT)
{
::SendMessage(GetParent()->GetSafeHwnd(), WM_COMMAND, ID_FILE_EXPORT, NULL);
}
else
{
(void) ::SendMessage(hwnd, WM_COMMAND, iSelection, NULL);
}
}
So my only gripe is that my own #define are values are using literal numbers and I would prefer them to be based on the IDM constants if possible. But either way, it all works fine!

CHtmlView and Print Preview and Context menu [duplicate]

So I keep coming back to this article on CodeProject:
https://www.codeproject.com/Articles/4758/How-to-customize-the-context-menus-of-a-WebBrowser
I then realised this statement at the top of the article:
The revised sample projects are using a new, much better customization approach that is going to be comprehensively discussed in the next update of this article, which will hopefully be ready in a couple of weeks. I am publishing this semi-documented and not fully-tested code, because I am having indications that some developers may need to have this code much sooner than the day of my next update. For each revised sample there is also a Readme.htm file that briefly describes how the sample works.
I thought I was struggling to understand the code in the article snippets vs the downloaded source! So I read the readme and it stated:
In MFC 7 CHtmlView has embedded support for IDocHostUIHandler, thus I simply override the CHtmlView::OnShowContextMenu method and afterwards I call the ::CustomShowContextMenu() function, (inside CustomMenus.cpp) which works like described in the section 5 of my original article.
So, I decided to add my own function override in my project:
HRESULT CChristianLifeMinistryHtmlView::OnShowContextMenu(DWORD dwID, LPPOINT ppt,
LPUNKNOWN pcmdtReserved, LPDISPATCH pdispReserved)
{
return CustomContextMenu(ppt, pcmdtReserved);
}
And I added the similar custom menu function:
HRESULT CustomContextMenu(POINT* ppt, IUnknown* pcmdtReserved)
{
IOleWindow* oleWnd = NULL;
HWND hwnd = NULL;
HMENU hMainMenu = NULL;
HMENU hPopupMenu = NULL;
HRESULT hr = 0;
INT iSelection = 0;
if ((ppt == NULL) || (pcmdtReserved == NULL))
goto error;
hr = pcmdtReserved->QueryInterface(IID_IOleWindow, (void**)&oleWnd);
if ((hr != S_OK) || (oleWnd == NULL))
goto error;
hr = oleWnd->GetWindow(&hwnd);
if ((hr != S_OK) || (hwnd == NULL))
goto error;
hMainMenu = LoadMenu(AfxGetInstanceHandle(),
MAKEINTRESOURCE(IDR_MENU_HTML_POPUP));
if (hMainMenu == NULL)
goto error;
hPopupMenu = GetSubMenu(hMainMenu, 0);
if (hPopupMenu == NULL)
goto error;
// Show shortcut menu
iSelection = ::TrackPopupMenu(hPopupMenu,
TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD,
ppt->x,
ppt->y,
0,
hwnd,
(RECT*)NULL);
// Send selected shortcut menu item command to shell
if (iSelection != 0)
(void) ::SendMessage(hwnd, WM_COMMAND, iSelection, NULL);
error:
if (hMainMenu != NULL)
::DestroyMenu(hMainMenu);
return S_OK;
}
Finally, I added a menu resource:
IDR_MENU_HTML_POPUP MENU
BEGIN
POPUP "CustomPopup"
BEGIN
MENUITEM "View Source", 2139
MENUITEM SEPARATOR
MENUITEM "Select All", 31
END
END
The menu ID values are based on the IDM_ versions and they all work.
I then tried to add my own menu item into that list with my own event handler and it shows as disabled.
Is it not possible to add our own menu items on the CHtmlView context menu?
I wanted to add my own menu item "Print Preview" which in turn simply posted a message to my parent "Editor" to simulate clicking "Print Preview" there. But it seems that any custom item that is added to this menu is always greyed out.
If I add a "Print Preview" menu item and give it a value of 2003(IDM_PRINTPREVIEW) it just triggers the original print preview mechanism. And I can't add my own event handler for the same to my CChristianLifeMinistryHtmlView class as it is not honoured.
I found this article which mentions:
Should you choose to replace the standard menu with your own, you can
still append menu extensions to your custom menu. Simply include a
blank IDM_MENUEXT_PLACEHOLDER menu option in your menu definition to
indicate where the custom commands are to be inserted. Menu extensions
are inserted just before this placeholder. You can also add your own
custom command to the standard menu by inserting the menu option
before IDM_MENUEXT_PLACEHOLDER, as shown in the following example.
#define IDM_MENUEXT_PLACEHOLDER 6047
// If the placeholder is gone or was never there, then just exit if
(GetMenuState(hMenu, IDM_MENUEXT_PLACEHOLDER, MF_BYCOMMAND) != (UINT)
-1) { InsertMenu(hMenu, // The Context Menu
IDM_MENUEXT_PLACEHOLDER, // The item to insert before
MF_BYCOMMAND|MF_STRING, // by item ID and str value
IDM_MENUEXT_FIRST__ + nExtCur, // the command ID
(LPTSTR)aOpts[nExtCur].pstrText);// The menu command text
// Remove placeholder DeleteMenu(hMenu, IDM_MENUEXT_PLACEHOLDER,
MF_BYCOMMAND); }
The menu IDs for extensions fall between IDM_MENUEXT_FIRST__ and IDM_MENUEXT_LAST__ for a maximum of 33 custom
commands.
I know I didn't design it right but I added a menu item for the place holder and then another for Print Preview with a menu item id of IDM_MENUEXT_FIRST__. I then added a menu handler to it. The menu item is no longer disabled so that is good. But clicking it does nothing.
This question relates to:
CHtmlView and Print Preview and Context menu
Update
I think I have found a solution and will provide an answer shortly.
I have got to the bottom of this. There were a few key things that I learned along the way.
Concept 1
I was not away of the CHtmlView::OnShowContextMenu function which I needed to implement:
HRESULT CChristianLifeMinistryHtmlView::OnShowContextMenu(DWORD dwID, LPPOINT ppt,
LPUNKNOWN pcmdtReserved, LPDISPATCH pdispReserved)
{
return CustomContextMenu(ppt, pcmdtReserved);
}
In my defence, the IDE in Visual Studio did not offer it in the list as a possibly override. But it existed non-the-less.
Concept 2
The menu IDs for all custom menu items fall between IDM_MENUEXT_FIRST__ and IDM_MENUEXT_LAST__ for a maximum of 33 custom commands. In my case I manually create some #define values in my resource.h file:
#define CUSTOM_MENU_PRINT_PREVIEW 3700
#define CUSTOM_MENU_EXPORT 3701
Note that I am not happy using literal values. I wish I could use IDM_MENU_EXT_FIRST + 1 etc. for my definitions but I do not know how to do that. Possible?
Concept 3
When you design your custom menu you can infill existing commands with the IDM_XXX values too:
IDR_MENU_HTML_POPUP MENU
BEGIN
POPUP "CustomPopup"
BEGIN
MENUITEM "Select All", 31
MENUITEM SEPARATOR
MENUITEM "Export", CUSTOM_MENU_EXPORT
MENUITEM SEPARATOR
MENUITEM "Page Setup", 2004
MENUITEM "Print Preview", CUSTOM_MENU_PRINT_PREVIEW
MENUITEM SEPARATOR
MENUITEM "Refresh", 2300
MENUITEM SEPARATOR
MENUITEM "View Source", 2139
END
END
The same note still applies though. I can't work out how to assign the IDM_* constants to my own #defines rather than using literal values.
Your custom menu items will be greyed out if you don't use the right ID values.
Concept 4
Then you have to create the context menu (see original question for that code).
Concept 5
This is closely related to item 4. TrackMenuPopup needed to be adjusted in my situation as follows:
// Show shortcut menu
iSelection = ::TrackPopupMenu(hPopupMenu,
TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD,
ppt->x,
ppt->y,
0,
hwnd,
(RECT*)NULL);
// Send selected shortcut menu item command to shell
if (iSelection != 0)
{
if (iSelection == CUSTOM_MENU_PRINT_PREVIEW)
{
::SendMessage(GetParent()->GetSafeHwnd(), WM_COMMAND, ID_FILE_PRINTPREVIEW, NULL);
}
else if (iSelection == CUSTOM_MENU_EXPORT)
{
::SendMessage(GetParent()->GetSafeHwnd(), WM_COMMAND, ID_FILE_EXPORT, NULL);
}
else
{
(void) ::SendMessage(hwnd, WM_COMMAND, iSelection, NULL);
}
}
The key was testing the return value of TrackMenuPopup and doing custom handling. In-fact, whilst writing this answer I now realise that my "Print Preview" menu item can be defined as the value of IDM_PRINTPREVIEW and I test again that, like this:
if (iSelection != 0)
{
if (iSelection == IDM_PRINTPREVIEW)
{
::SendMessage(GetParent()->GetSafeHwnd(), WM_COMMAND, ID_FILE_PRINTPREVIEW, NULL);
}
else if (iSelection == CUSTOM_MENU_EXPORT)
{
::SendMessage(GetParent()->GetSafeHwnd(), WM_COMMAND, ID_FILE_EXPORT, NULL);
}
else
{
(void) ::SendMessage(hwnd, WM_COMMAND, iSelection, NULL);
}
}
So my only gripe is that my own #define are values are using literal numbers and I would prefer them to be based on the IDM constants if possible. But either way, it all works fine!

c++ winapi: Move scrollbar after WM_SETTEXT to old position

I have this situation. I have two multiple line edit boxes. First is not editable and second yes. I catch EN_UPDATE message and when appears than I send updated text from second window to first window. So both of window have same text. Also If one is scrolled, than second one is scrolled too (mirrored behaviour).
Problem is that if I update text in first window after send new text from second window than scrollbar is moved at the start. If I use SetScrollPos than scrollbar is set, but text is not moved to correct position. I see the first line of text and I want to see position before update the text. How is this possible?
Update
I want that after SendMessage to first window like this to not to move window to the start position of text when replaced old text with new text. Because I have for example first window scrolled in the middle and after text is replaced that firstwindow is moved to the first line of new text but I want to stay in old position because I am updating only on letter in text in second window and than I send this change to firstWindow. But I resend all text.
SendMessage(firstWindow, WM_SETTEXT, 0, (LPARAM) buffer);
I create multiline text box like this:
firstWindow = CreateWindowEx(
0, TEXT("EDIT"), // predefined class
NULL, // no window title
WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_BORDER |
ES_READONLY | ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL,
TEXTBOX_START_X, TEXTBOX_START_Y, TEXTBOX_WIDTH, TEXTBOX_HEIGHT,
hWnd, // parent window
(HMENU) ID_TEXTBOX, // edit control ID
(HINSTANCE) GetWindowLong(hWnd, GWL_HINSTANCE),
NULL
);
savedWndProcTablet = (WNDPROC) SetWindowLongPtr(tabletWindowUtils.textboxHwnd, GWL_WNDPROC, (LONG_PTR) &textBoxProc);
Update 2
I try this:
char *buffer = new char[2];
buffer = "a\0";
DWORD l,r;
SendMessage(secondWindow, EM_GETSEL,(WPARAM)&l,(LPARAM)&r);
SendMessage(firstWindow, EM_REPLACESEL, 0, (LPARAM)buffer);
SendMessage(firstWindow, EM_SETSEL,l,r);
So I have some text in first window and where is position in second window I add new letter to this position. But this add one letter to correct position but it add no one letter but still adds aaaaaaaaaaaaaaaa. Why is it doing?
I can use only pure c++ and winapi.
Thanks.
If you want to copy consistently the whole text from second edit box to first, and ensure that scrolling position is correctly mirrored, you can just use:
// get the full text of second window
int len = ::GetWindowTextLength(secondWindow) + 1;
LPTSTR txt = new TCHAR[len];
::GetWindowText(secondWindow, txt, len);
// copies it to first one
::SetWindowText(firstWindow, txt);
// get scroll position of second window
SCROLLINFO si = { sizeof(SCROLLINFO) };
::GetScrollInfo(secondWindow, SB_VERT, &si);
// set scroll bar of first window accordingly
::SetScrollInfo(firstWindow, SB_VERT | SIF_PAGE | SIF_POS | SIF_RANGE, &si, TRUE );
// get first visible line in second window
int line = ::SendMessage(secondWindow, EM_GETFIRSTVISIBLELINE, 0, 0);
// skip to same line in first window
::SendMessage(firstWindow, EM_LINESCROLL, 0, line);
delete[] txt;
You could of course copy only a part of the text using EM_REPLACESEL, but you did not say how to find the new and old part, so I proposed to replace everything.

win32 select all on edit ctrl (textbox)

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?