2

我尝试使用 C++ 做一个记事本 ++ 插件。我需要在其中做一个可停靠的窗口。它应该看起来像 notepad++ 中的搜索窗口。我找不到解决方案。那么你能帮帮我吗?

我还有notepad++提供给我的代码“DockingFeature”。但是我不能创建一个可停靠的窗口。

//静态对话框.h

#ifndef STATIC_DIALOG_H
#define STATIC_DIALOG_H

//#include "resource.h"
#include "Window.h"
#include "Notepad_plus_msgs.h"

enum PosAlign{ALIGNPOS_LEFT, ALIGNPOS_RIGHT, ALIGNPOS_TOP, ALIGNPOS_BOTTOM};

struct DLGTEMPLATEEX {
  WORD   dlgVer;
  WORD   signature;
  DWORD  helpID;
  DWORD  exStyle;
  DWORD  style; 
  WORD   cDlgItems;
  short  x;
  short  y;    
  short  cx;
  short  cy;
  // The structure has more fields but are variable length
} ;

class StaticDialog : public Window
{
public :
StaticDialog() : Window() {};
~StaticDialog(){
    if (isCreated()) {
        ::SetWindowLongPtr(_hSelf, GWL_USERDATA, (long)NULL);   //Prevent run_dlgProc from doing   anything, since its virtual
        destroy();
    }
};
virtual void create(int dialogID, bool isRTL = false);

virtual bool isCreated() const {
    return (_hSelf != NULL);
};

void goToCenter();
void destroy() {
    ::SendMessage(_hParent, NPPM_MODELESSDIALOG, MODELESSDIALOGREMOVE, (WPARAM)_hSelf);
    ::DestroyWindow(_hSelf);
};

 protected :
RECT _rc;
static BOOL CALLBACK dlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
virtual BOOL CALLBACK run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam) = 0;

void alignWith(HWND handle, HWND handle2Align, PosAlign pos, POINT & point);
HGLOBAL makeRTLResource(int dialogID, DLGTEMPLATE **ppMyDlgTemplate);
};

 #endif //STATIC_DIALOG_H

//staticDialog.cpp

#include "StaticDialog.h"

void StaticDialog::goToCenter()
{
RECT rc;
::GetClientRect(_hParent, &rc);
POINT center;
center.x = rc.left + (rc.right - rc.left)/2;
center.y = rc.top + (rc.bottom - rc.top)/2;
::ClientToScreen(_hParent, &center);

int x = center.x - (_rc.right - _rc.left)/2;
int y = center.y - (_rc.bottom - _rc.top)/2;

::SetWindowPos(_hSelf, HWND_TOP, x, y, _rc.right - _rc.left, _rc.bottom - _rc.top, SWP_SHOWWINDOW);
}

HGLOBAL StaticDialog::makeRTLResource(int dialogID, DLGTEMPLATE **ppMyDlgTemplate)
{
// Get Dlg Template resource
HRSRC  hDialogRC = ::FindResource(_hInst, MAKEINTRESOURCE(dialogID), RT_DIALOG);
HGLOBAL  hDlgTemplate = ::LoadResource(_hInst, hDialogRC);
DLGTEMPLATE *pDlgTemplate = (DLGTEMPLATE *)::LockResource(hDlgTemplate);

// Duplicate Dlg Template resource
unsigned long sizeDlg = ::SizeofResource(_hInst, hDialogRC);
HGLOBAL hMyDlgTemplate = ::GlobalAlloc(GPTR, sizeDlg);
*ppMyDlgTemplate = (DLGTEMPLATE *)::GlobalLock(hMyDlgTemplate);

::memcpy(*ppMyDlgTemplate, pDlgTemplate, sizeDlg);

DLGTEMPLATEEX *pMyDlgTemplateEx = (DLGTEMPLATEEX *)*ppMyDlgTemplate;
if (pMyDlgTemplateEx->signature == 0xFFFF)
    pMyDlgTemplateEx->exStyle |= WS_EX_LAYOUTRTL;
else
    (*ppMyDlgTemplate)->dwExtendedStyle |= WS_EX_LAYOUTRTL;

return hMyDlgTemplate;
}

void StaticDialog::create(int dialogID, bool isRTL)
{
if (isRTL)
{
    DLGTEMPLATE *pMyDlgTemplate = NULL;
    HGLOBAL hMyDlgTemplate = makeRTLResource(dialogID, &pMyDlgTemplate);
    _hSelf = ::CreateDialogIndirectParam(_hInst, pMyDlgTemplate, _hParent, (DLGPROC)dlgProc, (LPARAM)this);
    ::GlobalFree(hMyDlgTemplate);
}
else
    _hSelf = ::CreateDialogParam(_hInst, MAKEINTRESOURCE(dialogID), _hParent, (DLGPROC)dlgProc,  (LPARAM)this);

if (!_hSelf)
{
    return;
}

::SendMessage(_hParent, NPPM_MODELESSDIALOG, MODELESSDIALOGADD, (WPARAM)_hSelf);
}

BOOL CALLBACK StaticDialog::dlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 
{
switch (message) 
{
    case WM_INITDIALOG :
    {
        StaticDialog *pStaticDlg = (StaticDialog *)(lParam);
        pStaticDlg->_hSelf = hwnd;
        ::SetWindowLongPtr(hwnd, GWL_USERDATA, (long)lParam);
        ::GetWindowRect(hwnd, &(pStaticDlg->_rc));
        pStaticDlg->run_dlgProc(message, wParam, lParam);

        return TRUE;
    }

    default :
    {
        StaticDialog *pStaticDlg = (StaticDialog *)(::GetWindowLongPtr(hwnd, GWL_USERDATA));
        if (!pStaticDlg)
            return FALSE;
        return pStaticDlg->run_dlgProc(message, wParam, lParam);
    }
}
}

void StaticDialog::alignWith(HWND handle, HWND handle2Align, PosAlign pos, POINT & point)
{
RECT rc, rc2;
::GetWindowRect(handle, &rc);

point.x = rc.left;
point.y = rc.top;

switch (pos)
{
    case ALIGNPOS_LEFT :
        ::GetWindowRect(handle2Align, &rc2);
        point.x -= rc2.right - rc2.left;
        break;

    case ALIGNPOS_RIGHT :
        ::GetWindowRect(handle, &rc2);
        point.x += rc2.right - rc2.left;
        break;

    case ALIGNPOS_TOP :
        ::GetWindowRect(handle2Align, &rc2);
        point.y -= rc2.bottom - rc2.top;
        break;

    default : //ALIGNPOS_BOTTOM
        ::GetWindowRect(handle, &rc2);
        point.y += rc2.bottom - rc2.top;
        break;
    }

    ::ScreenToClient(_hSelf, &point);
}
4

0 回答 0