question

MichaelSabo avatar image
0 Votes"
MichaelSabo asked MichaelSabo commented

Windows Runtime Library (WRL) and C++/MFC

What's the best thread for a strange error in WRL?
Who are able to debugging the method OnLayout() on website Tablet mode


c++
· 8
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

@MichaelSabo-0795

Is it an MFC app? What do you mean the best thread for a strange error in WRL? What's the strange error? Could you please provide a sample for us to reproduce the issue?

0 Votes 0 ·

Yes, of course. I already created for me an new assistant generated MFC project, added the function and call the function in WM_SETTINGCHANGE. To reproduce the error comment out the call in OnInitDialog. I can you upload these small project as .zip, but this file type is not allowed here.

0 Votes 0 ·

@MichaelSabo-0795

I suggest you could try to share the code directly to Onedrive.

0 Votes 0 ·
Show more comments

What is the strange error ?

Thanks

0 Votes 0 ·

In short:

The sample code initializes com and de-initializes com at the end. Although this is not very optimized and effective instead of only doing this once at the start and end of the program,
but works to call this function / method when receiving WM_SETTINGCHANGE with UserInteractionMode notification.

But if I also call this function / method in OnInitDialog to initialize the user interface, the method works once, but every further call in WM_SETTINGCHANGE fails with 0x80070776 (object exporter specified was not found)

0 Votes 0 ·

I forgot. If you do the com-initialization and de-initialization optimized, then it works. But it would still be interesting to know why that makes a difference.

0 Votes 0 ·

Can someone else reproduce this?

0 Votes 0 ·
RLWA32-6355 avatar image
0 Votes"
RLWA32-6355 answered MichaelSabo commented

Using the sample code provided I reproduced the assertion.

It seems that when the RoInitializeWrapper class is used within the CheckTabletMode method the runtime wants the MTA to exist. After making the following addition for the MTA the CheckTabletMode method no longer asserted with error 0x80070776.

I used this helper class to create/destroy the MTA and used it within the CheckTabletMode method.

 class CMTA {
 public:
     CO_MTA_USAGE_COOKIE cookie{};
     HRESULT m_hr;
     CMTA() : m_hr(CoIncrementMTAUsage(&cookie)) { }
     ~CMTA() { if (SUCCEEDED(m_hr)) CoDecrementMTAUsage(cookie); }
     operator HRESULT() const { return m_hr; }
 };

I also inserted a function to output the type of COM apartment that the thread was in after the RoInitializeWrapper object was instantiated.

 void QueryApartmentType()
 {
     APTTYPE aType{};
     APTTYPEQUALIFIER aQual{};
     CString strApt, strQual;
    
     HRESULT hr = CoGetApartmentType(&aType, &aQual);
     _ASSERT(SUCCEEDED(hr));
    
     switch (aType)
     {
     case APTTYPE_CURRENT:
         strApt = _T("Current thread");
         break;
     case APTTYPE_STA:
         strApt = _T("STA");
         break;
     case APTTYPE_MTA:
         strApt = _T("MTA");
         break;
     case APTTYPE_NA:
         strApt = _T("NA");
         break;
     case APTTYPE_MAINSTA:
         strApt = _T("Main STA");
         break;
     }
    
     switch (aQual)
     {
     case APTTYPEQUALIFIER_NONE:
         strQual = _T("None");
         break;
     case APTTYPEQUALIFIER_IMPLICIT_MTA:
         strQual = _T("Implicit MTA");
         break;
     case APTTYPEQUALIFIER_NA_ON_MTA:
         strQual = _T("NA on MTA");
         break;
     case APTTYPEQUALIFIER_NA_ON_STA:
         strQual = _T("NA on STA");
         break;
     case APTTYPEQUALIFIER_NA_ON_IMPLICIT_MTA:
         strQual = _T("NA on Implicit MTA");
         break;
     case APTTYPEQUALIFIER_NA_ON_MAINSTA:
         strQual = _T("NA on Main STA");
         break;
     case APTTYPEQUALIFIER_APPLICATION_STA:
         strQual = _T("Application STA");
         break;
     case APTTYPEQUALIFIER_RESERVED_1:
         strQual = _T("Reserved");
         break;
     }
    
     TRACE(_T("Apartment type : %s, Apartment type qualifier : %s\n"), strApt, strQual);
 }

This is where the above were inserted in the CheckTabletMode method -

 bool CSampleDlg::CheckTabletMode(const bool bMultithreaded, const HWND hWnd)
 {
     //
     // COM-Initialisierung
     //
    
     CMTA mta; // Create the MTA
     _ASSERT(SUCCEEDED(mta));
    
     RO_INIT_TYPE com_thread_initialization = RO_INIT_SINGLETHREADED;
     if (bMultithreaded)
         com_thread_initialization = RO_INIT_MULTITHREADED;
    
     RoInitializeWrapper initialize(com_thread_initialization);
     _ASSERT(SUCCEEDED(initialize));
     if (FAILED(initialize))
     {
         SetLastError(0x1);
         return false;
     }
    
     // What Apartment is this thread in
     QueryApartmentType();
· 5
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Sounds like a workaround (I think something in the core code have to be fixed), but it works! ;)

I have an additional visual issue about tablet mode. Are you also the right guy for it?
But I would create a new ticket else.

If I switch into tablet mode (manually) and goto into the task switch view, all applications already maximized, but not the sample application (see red rectangle).
122329-task-switch-screen.jpg

The question is, is this done by programmer or does this do windows automatically?
I can't believe that every "old" application was modified and optimized for tablet mode. But you can see notepad is also maximed. It looks, that Windows just automatically maximize every application, except mine. ;)

Of course, I can do a maximation self in code after event WM_SETTINGSCHANGED. Then the application is also shown maximized in the preview. But then I have other small issues.
Most importantly, there are several ways to maximize a window. The question is which one to prefer.



0 Votes 0 ·

I suggest you ask a new question regarding window maximization. My hardware doesn't have tablet mode.

0 Votes 0 ·

If you select the dialog window from the task view doesn't Windows maximize it automatically?

0 Votes 0 ·

Yes. It's only in the task view wrong before you have selected once.
BTW: I'm also using just a standard deskotop pc.

0 Votes 0 ·

If you like to follow the new thread.


0 Votes 0 ·
JeanineZhang-MSFT avatar image
0 Votes"
JeanineZhang-MSFT answered MichaelSabo published

Hi,

I suggest you could try to use ComPtr::GetAddressOf instead of &.

For example:

 HRESULT hr = GetActivationFactory(
     HStringReference(RuntimeClass_Windows_UI_ViewManagement_UIViewSettings).Get(), 
     uiViewSettingsInterop.GetAddressOf());

GetAddressOf - Retrieves the address of the ptr_ data member, which contains a pointer to the interface represented by this ComPtr.

Operator& - Releases the interface associated with this ComPtr object and then retrieves the address of the ComPtr object.

Best Regards,

Jeanine


If the response is helpful, please click "Accept Answer" and upvote it.

Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.



· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Thanks for your response, but did you execute the sample?
My session breaks in

 hr = uiViewSettingsInterop->GetForWindow(hWnd, IID_PPV_ARGS(&uiViewSettings));

not in

 HRESULT hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_ViewManagement_UIViewSettings).Get(), &uiViewSettingsInterop);


Didn't you get an assertion?

BTW:
The code is identically what I found on site https://docs.microsoft.com/en-us/windows-hardware/design/device-experiences/continuum#creating-an-app-that-interacts-with-tablet-mode-apis





0 Votes 0 ·