Initializing the COM library in apartment threaded mode in a thread with no message loop

221 Views Asked by At

According to the documentation, if the COM library is initialized in "apartment threaded" mode, the thread must have a message loop.

However, I found that using COM in a thread with no message loop works just fine. Here is a working example that demonstrate it.

#include <iostream>
#include <oleacc.h>

using namespace std ;

int main(){
    auto dektopWin = GetDesktopWindow() ;
    
    POINT point{} ;
    GetCursorPos(&point) ;
    
    auto hWnd = ChildWindowFromPoint(dektopWin, point) ;
    
    if( hWnd && hWnd!=dektopWin ){
        CoInitializeEx(NULL, COINIT_APARTMENTTHREADED) ;
        IAccessible* accPtr{} ;
        auto result = AccessibleObjectFromWindow(hWnd, OBJID_WINDOW, IID_IAccessible, (void**)&accPtr) ;
        if( result==S_OK ){
            RECT rect{} ;
            VARIANT VAR_CHILDID_SELF{VT_I4, 0,0,0, CHILDID_SELF} ;
            result = accPtr->accLocation(&rect.left, &rect.top, &rect.right, &rect.bottom, VAR_CHILDID_SELF) ;
            if( result==S_OK ){
                cout << "Window coordinates"
                     << rect.left << " "
                     << rect.top << " "
                     << rect.right << " "
                     << rect.bottom << endl ;
                return 0 ;
            }
        }
    }
    cout << "Something went wrong" ;
}

The program calls the IAccessible::accLocation method on the window under the mouse and then prints the window coordinates to the console.

Why does this code works if there's no message loop?
Can you explain what sort of situation requires the thread to have a message loop?


Alternative version of the code:

#include <iostream>
#include <oleacc.h>

using namespace std ;

void printWinAccLocation(HWND win){
    IAccessible* accPtr{} ;
    auto result = AccessibleObjectFromWindow(win, OBJID_WINDOW, IID_IAccessible, (void**)&accPtr) ;
    if( result==S_OK ){
        RECT rect{} ;
        VARIANT VAR_CHILDID_SELF{VT_I4, 0,0,0, CHILDID_SELF} ;
        result = accPtr->accLocation(&rect.left, &rect.top, &rect.right, &rect.bottom, VAR_CHILDID_SELF) ;
        accPtr->Release() ;
        if( result==S_OK ){
            cout << "Window coordinates "
                 << rect.left << " "
                 << rect.top << " "
                 << rect.right << " "
                 << rect.bottom << endl ;
        }
    }
}

int main(){
    auto dektopWin = GetDesktopWindow() ;
    
    POINT point{} ;
    GetCursorPos(&point) ;
    
    auto win = ChildWindowFromPoint(dektopWin, point) ;
    
    if( win && win!=dektopWin ){
        CoInitializeEx(NULL, COINIT_APARTMENTTHREADED) ;
        
        printWinAccLocation(win) ;
        Sleep(2000) ; //is the thread idle here?
        printWinAccLocation(win) ;
        Sleep(2000) ; //also here?
        printWinAccLocation(win) ;
        
        CoUninitialize() ;
    }
}
0

There are 0 best solutions below