Community
    • 登入

    Creating a docked window from a background thread

    已排程 已置頂 已鎖定 已移動 Notepad++ & Plugin Development
    14 貼文 3 Posters 7.0k 瀏覽
    正在載入更多貼文
    • 從舊到新
    • 從新到舊
    • 最多點贊
    回覆
    • 在新貼文中回覆
    登入後回覆
    此主題已被刪除。只有擁有主題管理權限的使用者可以查看。
    • Claudia FrankC
      Claudia Frank @Vitaliy Dovgan
      最後由 編輯

      @Vitaliy-Dovgan

      For me it sounds like you are running into some kind of race condition.
      One thread might receives the window messages whereas the other
      threads expect it. Did you check this?

      Cheers
      Claudia

      1 條回覆 最後回覆 回覆 引用 0
      • Vitaliy DovganV
        Vitaliy Dovgan
        最後由 編輯

        That must be it. MSDN says “GetMessage - Retrieves a message from the calling thread’s message queue”:
        https://msdn.microsoft.com/en-us/library/ms644936(VS.85).aspx
        Anyway, creating a dialog in a main thread and then calling NPPM_DMMREGASDCKDLG and NPPM_DMMSHOW from another thread does the trick.

        Though there’s another thing I don’t understand, this time in Notepad++. Why a docked dialog becomes visible immediately after NPPM_DMMREGASDCKDLG and MODELESSDIALOGADD? I mean, logically MODELESSDIALOGADD means “add a dialog” - correct? - so a dialog should not be shown before NPPM_DMMSHOW is sent explicitly!

        1 條回覆 最後回覆 回覆 引用 0
        • dailD
          dail
          最後由 編輯

          AFAIK it is not shown by default. You might check your config.xml file because it stores information about docked dialogs (position, visibility, etc). It might think it is supposed to be open already.

          1 條回覆 最後回覆 回覆 引用 0
          • Vitaliy DovganV
            Vitaliy Dovgan
            最後由 編輯

            Nope! In the “config.xml” there is:

            isVisible="no".
            

            And here is some verification code:

            ::OutputDebugStringA(::IsWindowVisible(hDialogWnd) ? "1. Visible\n" : "1. Not visible\n");
            SendNppMsg( NPPM_DMMREGASDCKDLG, 0, (LPARAM) &dockData );
            SendNppMsg( NPPM_MODELESSDIALOG, (WPARAM) MODELESSDIALOGADD, (LPARAM) hDialogWnd );
            ::OutputDebugStringA(::IsWindowVisible(hDialogWnd) ? "2. Visible\n" : "2. Not visible\n");
            

            It shows:

            1. Not visible
            2. Visible
            

            If there was isVisible=“yes” in the “config.xml”, there would be an additional explicit call of the function which functionId was specified as the dockData.dlgID. But in my case isVisible=“no”, there was no explicit call of the plugin’s function - but the docked window became visible…

            Claudia FrankC 1 條回覆 最後回覆 回覆 引用 0
            • dailD
              dail
              最後由 編輯

              My LuaScript plugin uses a docked dialog and is not shown by default (assuming the config.xml doesn’t contain any info about it).

              Take a look at this section of code which is how I’ve been doing it.

              1 條回覆 最後回覆 回覆 引用 0
              • Claudia FrankC
                Claudia Frank @Vitaliy Dovgan
                最後由 編輯

                @Vitaliy-Dovgan

                that is strange, indeed.
                Npp, does more or less the same checkings before creating the dialog

                	case NPPM_DMMREGASDCKDLG:
                	{
                		tTbData *pData = reinterpret_cast<tTbData *>(lParam);
                		int		iCont	= -1;
                		bool	isVisible	= false;
                
                		getIntegralDockingData(*pData, iCont, isVisible);
                		_dockingManager.createDockableDlg(*pData, iCont, isVisible);
                		return TRUE;
                	}
                

                …

                bool Notepad_plus::getIntegralDockingData(tTbData & dockData, int & iCont, bool & isVisible)
                {
                    DockingManagerData & dockingData = (DockingManagerData &)(NppParameters::getInstance())->getNppGUI()._dockingData;
                
                    for (size_t i = 0, len = dockingData._pluginDockInfo.size(); i < len ; ++i)
                    {
                        const PluginDlgDockingInfo & pddi = dockingData._pluginDockInfo[i];
                
                        if (!generic_stricmp(pddi._name.c_str(), dockData.pszModuleName) && (pddi._internalID == dockData.dlgID))
                        {
                            iCont				= pddi._currContainer;
                            isVisible			= pddi._isVisible;
                            dockData.iPrevCont	= pddi._prevContainer;
                
                            if (dockData.iPrevCont != -1)
                            {
                                int cont = (pddi._currContainer < DOCKCONT_MAX ? pddi._prevContainer : pddi._currContainer);
                                RECT rc;
                                if (dockingData.getFloatingRCFrom(cont, rc))
                                    dockData.rcFloat = rc;
                            }
                            return true;
                        }
                    }
                    return false;
                }
                

                …

                void DockingManager::createDockableDlg(tTbData data, int iCont, bool isVisible)
                {
                ...
                // if floated rect not set
                if (memcmp(&data.rcFloat, &rc, sizeof(RECT)) == 0)
                {
                	// set default rect state
                	::GetWindowRect(data.hClient, &data.rcFloat);
                
                	// test if dialog is first time created
                	if (iCont == -1)
                	{
                		// set default visible state
                		isVisible = (::IsWindowVisible(data.hClient) == TRUE);
                ...
                

                This would lead to the assumption that you might, maaayyyybeeee, checked
                the false config.xml?? I know you are familiar with npps configuration
                but, at least for me, sometimes you don’t see the wood for the trees.

                Cheers
                Claudia

                1 條回覆 最後回覆 回覆 引用 0
                • Vitaliy DovganV
                  Vitaliy Dovgan
                  最後由 編輯

                  Ah, looks I’ll need to debug Notepad++ to understand what is wrong.
                  Which is not straightforward because I’m having exactly the same issues with VS 2013 Express as mentioned here:
                  https://notepad-plus-plus.org/community/topic/11388/errors-building-current-repository
                  If you ask my opinion, I’d rather suggest to get rid of these CStringW in Notepad++'s code - these things are not true and pure Win API way!

                  Claudia FrankC 1 條回覆 最後回覆 回覆 引用 0
                  • Claudia FrankC
                    Claudia Frank @Vitaliy Dovgan
                    最後由 編輯

                    If you aren’t concerned about the new license agreements I would use the community edition
                    as this should behave like the pro versions.
                    If you still want to use express - didn’t the changes help?

                    Cheers
                    Claudia

                    1 條回覆 最後回覆 回覆 引用 0
                    • dailD
                      dail
                      最後由 編輯

                      @Vitaliy-Dovgan

                      Try calling NPPM_MODELESSDIALOG first.

                      1 條回覆 最後回覆 回覆 引用 0
                      • dailD
                        dail
                        最後由 編輯

                        Actually, if you look in Notepad++'s source where it uses these messages internally it normally calls:

                        1. NPPM_MODELESSDIALOG with MODELESSDIALOGADD
                        2. NPPM_MODELESSDIALOG with MODELESSDIALOGREMOVE
                        3. NPPM_DMMREGASDCKDLG

                        I think 1 and 2 are just a side effect of how the class inheritance works within Notepad++. So, it would appear that NPPM_MODELESSDIALOG may not even be needed for docked dialogs. I will look into this more if I get a chance.

                        1 條回覆 最後回覆 回覆 引用 0
                        • Vitaliy DovganV
                          Vitaliy Dovgan
                          最後由 編輯

                          @Claudia,
                          Yes, installing the WinDDK fixes that.
                          Though, as I said, I really don’t like Notepad++ to use ATL. Moreover, it’s just for a small feature, which could be rewritten.

                          @Dail,
                          I’ve found the root cause. It’s because my plugin has a toolbar icon and here is what Notepad++ does with it:

                          in DockingManager::createDockableDlg:

                          _vContainer[iCont]->createToolbar(data);
                          

                          where DockingCont::createToolbar calls DockingCont::viewToolbar, where the following is done:

                          // show dialog and notify parent to update dialog view
                          if (isVisible() == false)
                          {
                          	this->doDialog();
                          	::SendMessage(_hParent, WM_SIZE, 0, 0);
                          }
                          

                          So the docked dialog is forced to be shown by that code :(

                          1 條回覆 最後回覆 回覆 引用 0
                          • dailD
                            dail
                            最後由 編輯

                            That’s interesting. Can’t say I know for sure why that is calling createToolbar(). My plugin also uses a toolbar icon but it registers it during NPPN_TBMODIFICATION.

                            1 條回覆 最後回覆 回覆 引用 0
                            • 第一個貼文
                              最後的貼文
                            The Community of users of the Notepad++ text editor.
                            Powered by NodeBB | Contributors