Tag Archives: cpp

MFC: CHtmlEditCtrl – simple HTML Editor

Static control is needed to use CHtmlEditCtrl class.

BOOL CSomeDlg::OnInitDialog()
{
    ...

    // TODO: Add extra initialization here
    CStatic wndStatic;
    wndStatic.SubclassDlgItem(IDC_HTMLSTATIC, this);

    CRect rect;
    wndStatic.GetWindowRect(rect);
    ScreenToClient(rect);
    if (m_ctlEditHtml.Create(NULL, WS_CHILD | WS_VISIBLE, rect, this, IDC_HTMLSTATIC) != TRUE)
        return FALSE;

    return TRUE;
}

By the way, there is a bug with hiding the control: BUG: WebBrowser Control Destroyed When Hidden.

How to reproduce:

Consider the following code:

m_ctlEditHtml.ShowWindow(SW_HIDE);
m_ctlEditHtml.ShowWindow(SW_SHOW);

The application crashes!

Workaround:

::ShowWindow(m_ctlEditHtml.GetSafeHwnd(), SW_HIDE);             
::ShowWindow(m_ctlEditHtml.GetSafeHwnd(), SW_SHOW);

MAPI IMAPIProp SaveChanges call

My application creates a contact, sets properties and saves changes, after that it could not get the last modification time (MAPI_E_NO_ACCESS).
It seems that IMAPIProp::SaveChanges() member function should not be called with FORCE_SAVE flag (for the compatibility reasons with Outlook version less than 2003) if there is further property reading.
UseKEEP_OPEN_READWRITE instead.

Interesting consequence of MAPI threading rules violation

Have faced with an interesting consequence of MAPI threading rules violation.
Consider the following code:

CComPtr<IStream> prop_stream;
hr = props->OpenProperty(prop_tag, &IID_IStream, STGM_READWRITE, MAPI_CREATE | MAPI_MODIFY, (IUnknown**)&prop_stream);
if (FAILED(hr)) {
    return hr;
}

ULONG total_bytes_written = 0;
ULONG bytes_to_write = 0;
ULONG bytes_written = 0;
while (total_bytes_written < buffer.size()) {
    bytes_to_write = min(buffer.size() - total_bytes_written, BLOCK_SIZE);
    hr = prop_stream->Write(&buffer[total_bytes_written], bytes_to_write, &bytes_written);
    if (FAILED(hr)) {
        break;
    }
    total_bytes_written += bytes_written;
}

if (FAILED(hr)) {
    return hr;
}

hr = prop_stream->Commit(STGC_DEFAULT);
if (FAILED(hr)) {
    return hr;
}

The problem: if Outlook version is less 2003, Commit() member function call returns E_OUTOFMEMORY.
The root cause: forgot to initialize/un-initialize MAPI for the worker thread.

See more details: MAPI Multithreading Rules @ SGriffin’s MAPI Internals.