EM_SETHANDLE, EM_GETHANDLE works without DS_LOCALEDIT - c++

I made a program similar to Notepad using Visual Studio Community 2017 on Windows 10. It uses edit control created with CreateWindow with the following styles:
WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL
| WS_BORDER | ES_LEFT | ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL
As you see, there's no DS_LOCALEDIT.
However, using EM_SETHANDLE or EM_GETHANDLE to access the buffer within the edit control seems to work flawlessly. The following is a snippet of code that does initial buffer allocation for edit control that is supposed to have been created with DS_LOCALEDIT:
HLOCAL hEditMem = ::LocalAlloc(LPTR, sizeof(wchar_t) * 51);
wchar_t* pszEdit = reinterpret_cast<wchar_t*>(::LocalLock(hEditMem));
const std::wstring strData(L"Hello");
std::char_traits<wchar_t>::copy(pszEdit, strData.c_str(), strData.size());
::SendMessageW(hwndEdit, EM_SETHANDLE, reinterpret_cast<WPARAM>(hEditMem), 0);
::SendMessageW(hwndEdit, EM_SETMODIFY, TRUE, 0);
The documentation here clearly states that:
An application that uses the default allocation behavior (that is, does not use the
DS_LOCALEDIT style must not send EM_SETHANDLE and EM_GETHANDLE messages to the edit
control.
May be someone in Microsoft inconspicuously made the DS_LOCALEDIT no longer necessary as of Windows 10 or VS 2017 ?

Since no answer from anybody, I decided to answer my own ...
Using heuristic approach, I came to the following conclusions, which are unlike what's written on MSDN docs:
DS_LOCALEDIT is not a prerequisite for EM_SETHANDLE or EM_GETHANDLE, which means that the EM_XXXHANDLE can be used even when you're not managing the buffer customarily.
EM_GETHANDLE seems a far better choice than the WM_GETTEXT when all you need to do is just refer to a portion of text in edit control.
DS_LOCAEDIT seems to be obsolete, as I was able to set my own custom buffer without it. (As a side note, all I needed to do to increase the custom buffer, in response to EN_MAXTEXT, was to send EM_SETLIMITTEXT message with new size as parameter)
To me the second one was particularly important when implementing text find/replace using FindText and ReplaceText; you don't want to copy all the text from the edit control, using WM_GETTEXT, just to search for certain keyword, would you?
I still haven't tested if plain old new can substitute LocalAlloc when setting custom buffer with EM_SETHANDLE.

Related

Owner-draw with CTabCtrl using MFC

Using VS 2015. I have a dialog-based app (NOT a PropertySheet), and have a CTabCtrl-derived object in which I want to disable specific tabs. From what I've googled, owner-draw is the way to go. Fine, can understand that.
What I would like to do is START with an owner-drawn version that acts exactly like the non-owner-drawn version, and then start tweaking it variously to experiment. For example, I'd like to use things like
void CTabControl::DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct )
{
CTabCtrl::DrawItem( lpDrawItemStruct ); // do exactly what unmodified does
}
so that I am basically calling everything the unmodified CTabCtrl would do to accomplish the drawing. Even the simplest starting point would be helpful. What routines do I need to override or intercept to do this?
I'm setting TCS_OWNERDRAWFIXED in PreSubclassWindow() and doing what I showed above, and one or two other things, but the result definitely doesn't look the same. For one thing, no text in the tabs.
I'd really love it if I could get some pointers on where to start. BTW, I'm creating the control programatically (no dialog resources) like this (CTabControl inherits from CTabCtrl):
MyDlg::OnInitDialog()
{
...
m_tabctrl = new CTabControl();
m_tabctrl->Create( TCS_TABS | TCS_BOTTOM | TCS_HOTTRACK | TCS_FIXEDWIDTH | WS_CHILD | WS_VISIBLE, dummyRect, this, ID_TABCTRL );
...
}

CMFCShellTreeCtrl not displaying icons

I am programming with C++ and MFC.
I have a CMFCShellTreeCtrl as one of the child windows in my application. It is created like this:
const DWORD dwViewStyle = WS_CHILD | WS_VISIBLE | TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS;
m_wndFileView.Create(dwViewStyle, rectDummy, this, 4))
It displays correctly, but doesn't show any icons for the files. Just blank spaces where icons for folders/files should be. I looked at the function SHGetImageList, it could be my solution to get an appropriate image list and supply it to the Tree control, but I'm having trouble doing the conversion. The image list returned are of type IImageList, but I need CImageList.
Is there a way to convert between these two? Or is there a simple function to make the CMFCShellTreeCtrl show icons that I missed?
Any help would be appreciated.

C++ Win32 Multiline static label

I'm having a problem with multiple lines on a label.
I've tried using ES_MULTILINE, but whenever I use that I get a grey/black rectangle on the location of the label, without the text of the label.
CreateWindowW(L"STATIC", selectedPatternProblem, WS_CHILD | WS_VISIBLE | SS_LEFT | ES_MULTILINE | WM_CTLCOLORSTATIC,500, 190, 380, 90,*hwnd, (HMENU) 1, NULL, NULL);
And when I add WM_CTLCOLORSTATIC, the rectangle is gone, but so is my text.
The 'selectedPatternProblem' is too big to display on just one line, so my question is:
How can I display my label on multiple lines?
Edit: After deleting ES_MULTILINE and WM_CTLCOLORSTATIC, I found out my word was too long. But now I wonder how can I display one long word on multiple lines?
You're using an edit control style (ES_MULTILINE) with a static control, which is not designed to support it. That style probably maps to SS_BLACKRECT or SS_GRAYRECT, which would explain the behavior you're observing.
You should not have to add any style to your current control to achieve what you want, because you're already specifying SS_LEFT, and the documentation says:
SS_LEFT
A simple rectangle and left-aligns the text in the rectangle. The text
is formatted before it is displayed. Words that extend past the end of
a line are automatically wrapped to the beginning of the next
left-aligned line. Words that are longer than the width of the control
are truncated.
Since you're specifying neither SS_LEFTNOWORDWRAP nor one of the SS_*ELLIPSIS styles, the text should wrap between word boundaries.
Note you're also using the WM_CTLCOLORSTATIC message as a style, which will definitely not work as you expect. You should remove that value from your control's styles.
ES_MULTILINE is suitable for Edit controls not labels
MSDN:
Designates a multiline edit control. The default is single-line edit
control.
When the multiline edit control is in a dialog box, the default
response to pressing the ENTER key is to activate the default button.
I used an edit control as an alternative to multi line edit control. I had set the following properties in resource file
EDITTEXT IDC_COMMENT,58,53,75,41,ES_MULTILINE | ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER

Why would CToolBar::LoadToolBar fail?

I have been trying to add a toolbar to a dialog box and when I call m_ToolBar.LoadToolBar it fails.
I created a new toolbar resource and it's named IDR_TOOLBAR1, then I added this to the code
if(!m_ToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD |
WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS |
CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || !m_ToolBar.LoadToolBar(IDR_TOOLBAR1))
{
EndDialog(IDCANCEL);
}
For some reason m_ToolBar.LoadToolBar(IDR_TOOLBAR1) returns false. I created the toolbar resource in Visual Studio so I think that my IDR_TOOLBAR1 is set up correctly.
What could be causing the load to fail?
edit: I'm not sure if this is related, but I noticed that the ID for the toolbar matches the ID for another control
#define IDC_EDIT_EVENTS 213
#define IDR_TOOLBAR1 213
was in the auto-generated resource file
edit2: When I tried to debug LoadToolBar I found that it calls MAKEINTRESOURCE which seems to be returning bad pointers. MAKEINTRESOURCE is just a bunch of casts though so I'm not sure what the issue is here.
MAKEINTRESOURCE will return what appears to be a bad pointer, but this is normal. Resources can be strings or integers casted as strings.
Is this code by chance being compiled as a DLL? If so, maybe you need to add the following code to the top of the function to allow MFC to figure out which DLL to get it from.
AFX_MANAGE_STATE(AfxGetStaticModuleState());

Does LVS_EX_FULLROWSELECT have any compatibility issues with other styles?

I am trying to set the LVS_EX_FULLROWSELECT style on my grid list control as I want full row selection. However apparently it doesn't have any effect. Since I am using a number of other styles as well, I am wondering if LVS_EX_FULLROWSELECT has any compatibility issues with other styles. Anyone? Following are the styles I am setting.
Initially following styles are set on base list control class:
WS_CHILD|WS_BORDER|LVS_REPORT|LVS_SHOWSELALWAYS|LVS_SINGLESEL
Then I try to set additional styles in the derived grid list control class:
ListView_SetExtendedListViewStyleEx(sysId(), 0, LVS_EX_GRIDLINES | LVS_OWNERDATA | LVS_EX_FULLROWSELECT);
The second parameter is a mask, so you need:
ListView_SetExtendedListViewStyleEx(m_hWnd, LVS_EX_GRIDLINES | LVS_OWNERDATA | LVS_EX_FULLROWSELECT, LVS_EX_GRIDLINES | LVS_OWNERDATA | LVS_EX_FULLROWSELECT);
You need to send the LVM_SETEXTENDEDLISTVIEWSTYLE message to the control and specify the LVS_EX_FULLROWSELECT extended style (source: MS Support).
Edit:
Check the example. There is
ListView_SetExtendedListViewStyle(m_hWnd, ListView_GetExtendedListViewStyle(m_hWnd), VS_EX_FULLROWSELECT);
Try using ListView_GetExtendedListViewStyle(sysId()) instead of 0. BTW - does this sysId() of yours really retrieve the window handle? The name sounds somewhat different.
Cheers.