📄 windowsdlg.cpp
字号:
#include <windows.h>
#include "WindowsDlg.h"
#include "WindowsDlgRc.h"
#include "DocTabView.h"
#include <algorithm>
#include <functional>
#include <vector>
#ifndef _countof
#define _countof(x) (sizeof(x)/sizeof((x)[0]))
#endif
#ifndef LVS_EX_DOUBLEBUFFER
#define LVS_EX_DOUBLEBUFFER 0x00010000
#endif
static const TCHAR *readonlyString = TEXT(" [Read Only]");
const UINT WDN_NOTIFY = RegisterWindowMessage(TEXT("WDN_NOTIFY"));
inline static DWORD GetStyle(HWND hWnd) {
return (DWORD)GetWindowLongPtr(hWnd, GWL_STYLE);
}
inline static DWORD GetExStyle(HWND hWnd) {
return (DWORD)GetWindowLongPtr(hWnd, GWL_EXSTYLE);
}
inline static BOOL ModifyStyle(HWND hWnd, DWORD dwRemove, DWORD dwAdd) {
DWORD dwStyle = ::GetWindowLongPtr(hWnd, GWL_STYLE);
DWORD dwNewStyle = (dwStyle & ~dwRemove) | dwAdd;
if(dwStyle == dwNewStyle)
return FALSE;
::SetWindowLongPtr(hWnd, GWL_STYLE, dwNewStyle);
return TRUE;
}
inline static BOOL ModifyStyleEx(HWND hWnd, DWORD dwRemove, DWORD dwAdd) {
DWORD dwStyle = ::GetWindowLongPtr(hWnd, GWL_EXSTYLE);
DWORD dwNewStyle = (dwStyle & ~dwRemove) | dwAdd;
if(dwStyle == dwNewStyle)
return FALSE;
::SetWindowLongPtr(hWnd, GWL_EXSTYLE, dwNewStyle);
return TRUE;
}
struct NumericStringEquivalence
{
bool operator()(const TCHAR* s1, const TCHAR* s2) const
{ return numstrcmp(s1, s2) < 0; }
static inline int numstrcmp_get(const TCHAR **str, int *length)
{
const TCHAR *p = *str;
int value = 0;
for (*length = 0; isdigit(*p); (*length)++)
value = value * 10 + *p++ - '0';
*str = p;
return (value);
}
static int numstrcmp(const TCHAR *str1, const TCHAR *str2)
{
TCHAR *p1, *p2;
int c1, c2, lcmp;
for(;;)
{
c1 = tolower(*str1), c2 = tolower(*str2);
if ( c1 == 0 || c2 == 0 )
break;
else if (isdigit(c1) && isdigit(c2))
{
lcmp = generic_strtol(str1, &p1, 10) - generic_strtol(str2, &p2, 10);
if ( lcmp == 0 )
lcmp = (p2 - str2) - (p1 - str1);
if ( lcmp != 0 )
return (lcmp > 0 ? 1 : -1);
str1 = p1, str2 = p2;
}
else
{
lcmp = (c1 - c2);
if (lcmp != 0)
return (lcmp > 0 ? 1 : -1);
++str1, ++str2;
}
}
lcmp = (c1 - c2);
return ( lcmp < 0 ) ? -1 : (lcmp > 0 ? 1 : 0);
}
};
struct BufferEquivalent
{
NumericStringEquivalence _strequiv;
DocTabView *_pTab;
int _iColumn;
bool _reverse;
BufferEquivalent(DocTabView *pTab, int iColumn, bool reverse)
: _pTab(pTab), _iColumn(iColumn), _reverse(reverse)
{}
bool operator()(int i1, int i2) const
{
if (i1 == i2) return false; // equivalence test not equality
if (_reverse) std::swap(i1, i2);
return compare(i1, i2);
}
bool compare(int i1, int i2) const
{
BufferID bid1 = _pTab->getBufferByIndex(i1);
BufferID bid2 = _pTab->getBufferByIndex(i2);
Buffer * b1 = MainFileManager->getBufferByID(bid1);
Buffer * b2 = MainFileManager->getBufferByID(bid2);
if (_iColumn == 0)
{
const TCHAR *s1 = b1->getFileName();
const TCHAR *s2 = b2->getFileName();
return _strequiv(s1, s2);
}
else if (_iColumn == 1)
{
const TCHAR *s1 = b1->getFullPathName();
const TCHAR *s2 = b2->getFullPathName();
return _strequiv(s1, s2); //we can compare the full path to sort on directory, since after sorting directories sorting files is the second thing to do (if directories are the same that is)
}
else if (_iColumn == 2)
{
int t1 = (int)b1->getLangType();
int t2 = (int)b2->getLangType();
return (t1 < t2); // yeah should be the name
}
return false;
}
};
//////////////////
// Window map tells CWinMgr how to position dialog controls
//
BEGIN_WINDOW_MAP(WindowsDlgMap)
BEGINROWS(WRCT_REST,0,RCMARGINS(8,8))
BEGINCOLS(WRCT_REST,0,0) // Begin list control column
BEGINROWS(WRCT_REST,0,0)
RCREST(IDC_WINDOWS_LIST)
RCSPACE(20)
ENDGROUP()
RCSPACE(12)
BEGINROWS(WRCT_TOFIT,0,0)
RCSPACE(12)
RCTOFIT(IDOK)
RCSPACE(-12)
RCTOFIT(IDC_WINDOWS_SAVE)
RCSPACE(-12)
RCTOFIT(IDC_WINDOWS_CLOSE)
RCSPACE(-12)
RCTOFIT(IDC_WINDOWS_SORT)
RCREST(-1)
RCTOFIT(IDCANCEL)
ENDGROUP()
ENDGROUP()
ENDGROUP()
END_WINDOW_MAP()
RECT WindowsDlg::_lastKnownLocation;
WindowsDlg::WindowsDlg() : MyBaseClass(WindowsDlgMap), _isSorted(false)
{
_szMinButton = SIZEZERO;
_szMinListCtrl = SIZEZERO;
}
void WindowsDlg::init(HINSTANCE hInst, HWND parent, DocTabView *pTab)
{
MyBaseClass::init(hInst, parent);
_pTab = pTab;
}
void WindowsDlg::init(HINSTANCE hInst, HWND parent)
{
assert(!"Call other initialize method");
MyBaseClass::init(hInst, parent);
_pTab = NULL;
}
BOOL CALLBACK WindowsDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG :
{
changeDlgLang();
return MyBaseClass::run_dlgProc(message, wParam, lParam);
}
case WM_COMMAND :
{
switch (wParam)
{
case IDOK :
activateCurrent();
return TRUE;
case IDCANCEL :
::GetWindowRect(_hSelf, &_lastKnownLocation);
EndDialog(_hSelf, IDCANCEL);
return TRUE;
case IDC_WINDOWS_SAVE:
doSave();
return TRUE;
case IDC_WINDOWS_CLOSE:
doClose();
return TRUE;
case IDC_WINDOWS_SORT:
doSortToTabs();
_isSorted = false;
updateButtonState();
break;
default :
break;
}
}
case WM_DESTROY :
//destroy();
return TRUE;
case WM_NOTIFY :
{
if (wParam == IDC_WINDOWS_LIST)
{
NMHDR* pNMHDR = (NMHDR*)lParam;
if (pNMHDR->code == LVN_GETDISPINFO)
{
NMLVDISPINFO *pLvdi = (NMLVDISPINFO *)pNMHDR;
//if(pLvdi->item.mask & LVIF_IMAGE)
// ;
if(pLvdi->item.mask & LVIF_TEXT)
{
pLvdi->item.pszText[0] = 0;
int index = pLvdi->item.iItem;
if (index >= _pTab->nbItem() || index >= (int)_idxMap.size())
return FALSE;
index = _idxMap[index];
//const Buffer& buffer = _pView->getBufferAt(index);
BufferID bufID = _pTab->getBufferByIndex(index);
Buffer * buf = MainFileManager->getBufferByID(bufID);
if (pLvdi->item.iSubItem == 0) // file name
{
int len = pLvdi->item.cchTextMax;
const TCHAR *fileName = buf->getFileName();
generic_strncpy(pLvdi->item.pszText, fileName, len-1);
pLvdi->item.pszText[len-1] = 0;
len = lstrlen(pLvdi->item.pszText);
if (buf->isDirty())
{
if (len < pLvdi->item.cchTextMax)
{
pLvdi->item.pszText[len++] = '*';
pLvdi->item.pszText[len] = 0;
}
}
else if (buf->isReadOnly())
{
len += lstrlen(readonlyString);
if (len <= pLvdi->item.cchTextMax)
lstrcat(pLvdi->item.pszText, readonlyString);
}
}
else if (pLvdi->item.iSubItem == 1) // directory
{
const TCHAR *fullName = buf->getFullPathName();
const TCHAR *fileName = buf->getFileName();
int len = lstrlen(fullName)-lstrlen(fileName);
if (!len) {
len = 1;
fullName = TEXT("");
}
if (pLvdi->item.cchTextMax < len)
len = pLvdi->item.cchTextMax;
generic_strncpy(pLvdi->item.pszText, fullName, len-1);
pLvdi->item.pszText[len-1] = 0;
}
else if (pLvdi->item.iSubItem == 2) // Type
{
int len = pLvdi->item.cchTextMax;
NppParameters *pNppParameters = NppParameters::getInstance();
Lang *lang = pNppParameters->getLangFromID(buf->getLangType());
if (NULL != lang)
{
generic_strncpy(pLvdi->item.pszText, lang->getLangName(), len-1);
}
}
}
return TRUE;
}
else if (pNMHDR->code == LVN_COLUMNCLICK) // sort columns with stable sort
{
NMLISTVIEW *pNMLV = (NMLISTVIEW *)pNMHDR;
if (pNMLV->iItem == -1)
{
bool reverse = false;
int iColumn = pNMLV->iSubItem;
if (_lastSort == iColumn)
{
reverse = true;
_lastSort = -1;
}
else
{
_lastSort = iColumn;
}
int i;
int n = _idxMap.size();
vector<int> sortMap;
sortMap.resize(n);
for (i=0; i<n; ++i) sortMap[_idxMap[i]] = ListView_GetItemState(_hList, i, LVIS_SELECTED);
stable_sort(_idxMap.begin(), _idxMap.end(), BufferEquivalent(_pTab, iColumn, reverse));
for (i=0; i<n; ++i) ListView_SetItemState(_hList, i, sortMap[_idxMap[i]] ? LVIS_SELECTED : 0, LVIS_SELECTED);
::InvalidateRect(_hList, &_rc, FALSE);
_isSorted = true;
updateButtonState();
}
return TRUE;
}
else if (pNMHDR->code == LVN_ITEMACTIVATE || pNMHDR->code == LVN_ITEMCHANGED || pNMHDR->code == LVN_ODSTATECHANGED)
{
updateButtonState();
return TRUE;
}
else if (pNMHDR->code == NM_DBLCLK)
{
::PostMessage(_hSelf, WM_COMMAND, IDOK, 0);
//activateCurrent();
return TRUE;
}
else if (pNMHDR->code == LVN_KEYDOWN)
{
NMLVKEYDOWN *lvkd = (NMLVKEYDOWN *)pNMHDR;
// Ctrl+A
short ctrl = GetKeyState(VK_CONTROL);
short alt = GetKeyState(VK_MENU);
short shift = GetKeyState(VK_SHIFT);
if (lvkd->wVKey == 0x41/*a*/ && ctrl<0 && alt>=0 && shift>=0)
{
for (int i=0, n=ListView_GetItemCount(_hList); i<n; ++i)
ListView_SetItemState(_hList, i, LVIS_SELECTED, LVIS_SELECTED);
}
return TRUE;
}
}
}
break;
}
return MyBaseClass::run_dlgProc(message, wParam, lParam);
}
void WindowsDlg::updateButtonState()
{
int nSelection = ListView_GetSelectedCount(_hList);
if (nSelection == 0)
{
EnableWindow(GetDlgItem(_hSelf, IDOK), FALSE);
EnableWindow(GetDlgItem(_hSelf, IDC_WINDOWS_SAVE), FALSE);
EnableWindow(GetDlgItem(_hSelf, IDC_WINDOWS_CLOSE), FALSE);
}
else
{
EnableWindow(GetDlgItem(_hSelf, IDC_WINDOWS_SAVE), TRUE);
EnableWindow(GetDlgItem(_hSelf, IDC_WINDOWS_CLOSE), TRUE);
if (nSelection == 1)
EnableWindow(GetDlgItem(_hSelf, IDOK), TRUE);
else
EnableWindow(GetDlgItem(_hSelf, IDOK), FALSE);
}
EnableWindow(GetDlgItem(_hSelf, IDC_WINDOWS_SORT), _isSorted);
}
int WindowsDlg::doDialog(TiXmlNodeA *dlgNode)
{
_dlgNode = dlgNode;
return ::DialogBoxParam(_hInst, MAKEINTRESOURCE(IDD_WINDOWS), _hParent, (DLGPROC)dlgProc, (LPARAM)this);
};
bool WindowsDlg::changeDlgLang()
{
if (!_dlgNode) return false;
#ifdef UNICODE
WcharMbcsConvertor *wmc = WcharMbcsConvertor::getInstance();
int nativeLangEncoding = CP_ACP;
TiXmlDeclarationA *declaration = _dlgNode->GetDocument()->FirstChild()->ToDeclaration();
if (declaration)
{
const char * encodingStr = declaration->Encoding();
nativeLangEncoding = getCpFromStringValue(encodingStr);
}
#endif
// Set Title
const char *titre = (_dlgNode->ToElement())->Attribute("title");
if (titre && titre[0])
{
#ifdef UNICODE
const wchar_t *nameW = wmc->char2wchar(titre, nativeLangEncoding);
::SetWindowText(_hSelf, nameW);
#else
::SetWindowText(_hSelf, titre);
#endif
}
// Set the text of child control
for (TiXmlNodeA *childNode = _dlgNode->FirstChildElement("Item");
childNode ;
childNode = childNode->NextSibling("Item") )
{
TiXmlElementA *element = childNode->ToElement();
int id;
const char *sentinel = element->Attribute("id", &id);
const char *name = element->Attribute("name");
if (sentinel && (name && name[0]))
{
HWND hItem = ::GetDlgItem(_hSelf, id);
if (hItem)
{
#ifdef UNICODE
const wchar_t *nameW = wmc->char2wchar(name, nativeLangEncoding);
::SetWindowText(hItem, nameW);
#else
::SetWindowText(hItem, name);
#endif
}
}
}
return true;
}
BOOL WindowsDlg::onInitDialog()
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -