JavaScript
Code: Select all
// https://akelpad.sourceforge.net/forum/viewtopic.php?p=35182#p35182
// Author: The script remade Azjio from the Tabswitch.js script from Instructor
//
//
// Description(1033): Closes tabs of the specified type, for example, all htm files
// Description(1049): Закрывает вкладки определённого типа, например все htm-файлы
//
// Arguments:
// -CtrlTab=false -No Ctrl+Tab hotkey is assigned to TabSwitch.js (default is true).
// -MinTabs=2 -Minimum number of tabs before switch window appeared (default is 2).
// -FontName="Arial" -Font name. Unchanged, if "".
// -FontStyle=3 -Font style (one of the following):
// 0 ignored (default).
// 1 normal.
// 2 bold.
// 3 italic.
// 4 bold italic.
// -FontSize=10 -Font size. Unchanged, if 0 (default).
// -LineGap=10 -Space between items (default is 1).
// -SingleClick=false -Single mouse click chooses item (default is true).
// -ShowModify=2 -Show modification sign (one of the following):
// 0 hidden.
// 1 display asterisk * at the end (default).
// 2 display asterisk * at the beginning.
// -WindowLeft=100 -Left window position. Special values:
// -1 centered (default).
// -2 cursor position.
// -WindowTop=100 -Top window position. Special values:
// -1 centered (default).
// -2 cursor position.
// -WindowMaxHeight=500 -Maximum window height. Special values:
// -1 unlimited (default).
// -WindowMaxWidth=500 -Maximum window width. Special values:
// -1 unlimited (default).
//
// Usage:
// Toolbar button example:
// -"Close tabs by extension" Call("Scripts::Main", 1, "CloseTabByExt.js", `-CtrlTab=false -MinTabs=1 -WindowLeft=%bl -WindowTop=%bb`)
// ContextMenu item example:
// -"Close tabs by extension" Call("Scripts::Main", 1, "CloseTabByExt.js", `-CtrlTab=false -MinTabs=1 -WindowLeft=-2 -WindowTop=-2`)
//Arguments
var bCtrlTab = AkelPad.GetArgValue("CtrlTab", true);
var nMinTabs = AkelPad.GetArgValue("MinTabs", 2);
var pFontName = AkelPad.GetArgValue("FontName", "");
var nFontStyle = AkelPad.GetArgValue("FontStyle", 0);
var nFontSize = AkelPad.GetArgValue("FontSize", 0);
var nLineGap = AkelPad.GetArgValue("LineGap", 1);
var bSingleClick = AkelPad.GetArgValue("SingleClick", true);
var nWindowLeft = AkelPad.GetArgValue("WindowLeft", -1);
var nWindowTop = AkelPad.GetArgValue("WindowTop", -1);
var nWindowMaxHeight = AkelPad.GetArgValue("WindowMaxHeight", -1);
var nWindowMaxWidth = AkelPad.GetArgValue("WindowMaxWidth", -1);
var bAsk = AkelPad.GetArgValue("Ask", false);
//Variables
var hMainWnd = AkelPad.GetMainWnd();
var hWndEdit = AkelPad.GetEditWnd();
var oSys = AkelPad.SystemFunction();
var hInstanceDLL = AkelPad.GetInstanceDll();
var pClassName = "AkelPad::Scripts::" + WScript.ScriptName + "::" + oSys.Call("kernel32::GetCurrentProcessId");
var hWndContainer = 0;
var hWndListBox = 0;
var hHookPost;
var hHookSend;
var dwMainThreadID = oSys.Call("user32::GetWindowThreadProcessId", hMainWnd, 0);
var hSubClass;
var hDC;
var hBrushHollow;
var hFontEdit;
var lpFrameList = [];
var lpAllList = [];
var rcMain = [];
var ptPoint = [];
var nItemHeight;
var nScreenWidth;
var nControlWidth;
var nControlHeight;
var nMaxControlHeight;
var nCharWidth;
var nCharHeight;
var nMaxCharWidth = 0;
var nMaxCharHeight = 0;
var nIconSize = 16;
var nIconGap = 2;
var bNoSwitch = false;
var i;
//Get list of documents
nCurSel = GetFrameList(lpFrameList, lpAllList);
// WScript.Echo(lpFrameList.length);
if (lpFrameList.length > 0)
// if (lpFrameList.length >= nMinTabs && lpFrameList.length > 0)
{
//Get font
if (pFontName || nFontStyle || nFontSize)
hFontEdit = CreateFont(pFontName, nFontStyle, nFontSize);
else
hFontEdit = AkelPad.SendMessage(hWndEdit, 0x31 /*WM_GETFONT*/ , 0, 0);
if (!hFontEdit) WScript.Quit();
//Get maximum character size
if (lpSize = AkelPad.MemAlloc(8 /*sizeof(SIZE)*/ )) {
if (hDC = oSys.Call("user32::GetDC", hWndEdit)) {
oSys.Call("gdi32::SelectObject", hDC, hFontEdit);
for (i = 0; i < lpFrameList.length; ++i) {
if (oSys.Call("gdi32::GetTextExtentPoint32" + _TCHAR, hDC, lpFrameList[i][0], lpFrameList[i][0].length, lpSize)) {
nCharWidth = AkelPad.MemRead(_PtrAdd(lpSize, 0) /*offsetof(SIZE, cx)*/ , 3 /*DT_DWORD*/ );
nCharHeight = AkelPad.MemRead(_PtrAdd(lpSize, 4) /*offsetof(SIZE, cy)*/ , 3 /*DT_DWORD*/ );
if (nCharWidth > nMaxCharWidth) nMaxCharWidth = nCharWidth;
if (nCharHeight > nMaxCharHeight) nMaxCharHeight = nCharHeight;
}
}
oSys.Call("user32::ReleaseDC", hWndEdit, hDC);
}
nMaxCharWidth += nIconSize + nIconGap + 16;
AkelPad.MemFree(lpSize);
}
//Create dialog
if (AkelPad.WindowRegisterClass(pClassName, 0x21 /*WM_MOUSEACTIVATE*/ ,
0x2B /*WM_DRAWITEM*/ )) {
if (hWndContainer = oSys.Call("user32::CreateWindowEx" + _TCHAR, 0, pClassName, 0, 0x80000000 /*WS_POPUP*/ , 0, 0, 0, 0, hMainWnd, 0, hInstanceDLL, DialogCallback)) {
if (hWndListBox = oSys.Call("user32::CreateWindowEx" + _TCHAR, 0, "LISTBOX", 0, 0x50700010 /*WS_VISIBLE|WS_CHILD|WS_HSCROLL|WS_VSCROLL|WS_DLGFRAME|LBS_OWNERDRAWFIXED*/ , 0, 0, 0, 0, hWndContainer, 0, hInstanceDLL, 0)) {
//Make hWndContainer invisible
hBrushHollow = oSys.Call("gdi32::GetStockObject", 5 /*HOLLOW_BRUSH*/ );
oSys.Call("user32::SetClassLong" + _TCHAR, hWndContainer, -10 /*GCL_HBRBACKGROUND*/ , hBrushHollow);
AkelPad.SendMessage(hWndListBox, 48 /*WM_SETFONT*/ , hFontEdit, 1);
nItemHeight = nMaxCharHeight + nLineGap;
i = AkelPad.SendMessage(hWndListBox, 0x1A1 /*LB_GETITEMHEIGHT*/ , 0, 0);
if (nItemHeight < i)
nItemHeight = i;
else
AkelPad.SendMessage(hWndListBox, 0x1A0 /*LB_SETITEMHEIGHT*/ , 0, nItemHeight);
nMaxControlHeight = lpFrameList.length * nItemHeight + oSys.Call("user32::GetSystemMetrics", 8 /*SM_CYDLGFRAME*/ ) * 2;
if (nWindowMaxHeight > 0)
nControlHeight = Math.min(nWindowMaxHeight, nMaxControlHeight);
else
nControlHeight = nMaxControlHeight;
nControlHeight = Math.min(oSys.Call("user32::GetSystemMetrics", 62 /*SM_CYMAXIMIZED*/ ) - 8, nControlHeight);
if (nWindowMaxWidth > 0)
nControlWidth = Math.min(nWindowMaxWidth, nMaxCharWidth);
else
nControlWidth = nMaxCharWidth;
nControlWidth = Math.min(oSys.Call("user32::GetSystemMetrics", 61 /*SM_CXMAXIMIZED*/ ) - 8, nControlWidth);
if (nMaxCharWidth > nControlWidth) {
AkelPad.SendMessage(hWndListBox, 0x194 /*LB_SETHORIZONTALEXTENT*/ , nMaxCharWidth, 0);
if (nMaxControlHeight == nControlHeight)
nControlHeight += oSys.Call("user32::GetSystemMetrics", 21 /*SM_CXHSCROLL*/ );
}
//Fill listbox
for (i = 0; i < lpFrameList.length; ++i)
oSys.Call("user32::SendMessage" + _TCHAR, hWndListBox, 0x180 /*LB_ADDSTRING*/ , 0, lpFrameList[i][0]);
GetWindowSize(hMainWnd, 0, rcMain);
if (nWindowLeft >= 0)
rcMain.left = nWindowLeft;
else if (nWindowLeft == -2) {
GetCursorPos(ptPoint);
rcMain.left = ptPoint.x;
} else
rcMain.left += rcMain.right / 2 - nControlWidth / 2;
if (!(nScreenWidth = oSys.Call("user32::GetSystemMetrics", 78 /*SM_CXVIRTUALSCREEN*/ )))
nScreenWidth = oSys.Call("user32::GetSystemMetrics", 61 /*SM_CXMAXIMIZED*/ );
rcMain.left = Math.min(rcMain.left, Math.max((nScreenWidth - 8) - nControlWidth, 0));
if (rcMain.left < 0) rcMain.left = 0;
if (nWindowTop >= 0)
rcMain.top = nWindowTop;
else if (nWindowTop == -2) {
GetCursorPos(ptPoint);
rcMain.top = ptPoint.y;
} else
rcMain.top += rcMain.bottom / 2 - nControlHeight / 2;
rcMain.top = Math.min(rcMain.top, Math.max((oSys.Call("user32::GetSystemMetrics", 62 /*SM_CYMAXIMIZED*/ ) - 8) - nControlHeight, 0));
if (rcMain.top < 0) rcMain.top = 0;
oSys.Call("user32::SetWindowPos", hWndContainer, 0, rcMain.left, rcMain.top, nControlWidth, nControlHeight, 0x14 /*SWP_NOZORDER|SWP_NOACTIVATE*/ );
oSys.Call("user32::SetWindowPos", hWndListBox, 0, 0, 0, nControlWidth, nControlHeight, 0x16 /*SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE*/ );
AkelPad.SendMessage(hWndListBox, 0x186 /*LB_SETCURSEL*/ , nCurSel, 0);
oSys.Call("user32::ShowWindow", hWndContainer, 4 /*SW_SHOWNOACTIVATE*/ );
//oSys.Call("user32::SetFocus", hWndListBox);
//oSys.Call("user32::ShowWindow", hWndContainer, 5 /*SW_SHOW*/);
//oSys.Call("user32::UpdateWindow", hMainWnd);
//Cause listbox is non-active, hook and send to listbox keyboard and mouse actions.
if (hHookPost = AkelPad.ThreadHook(3 /*WH_GETMESSAGE*/ , HookPostCallback, dwMainThreadID, 0x201 /*WM_LBUTTONDOWN*/ ,
0x0A1 /*WM_NCLBUTTONDOWN*/ ,
0x204 /*WM_RBUTTONDOWN*/ ,
0x0A4 /*WM_NCRBUTTONDOWN*/ ,
0x207 /*WM_MBUTTONDOWN*/ ,
0x0A7 /*WM_NCMBUTTONDOWN*/ ,
0x100 /*WM_KEYDOWN*/ ,
0x101 /*WM_KEYUP*/ ,
0x104 /*WM_SYSKEYDOWN*/ ,
0x105 /*WM_SYSKEYUP*/ ,
0x20A /*WM_MOUSEWHEEL*/ )) {
if (hHookSend = AkelPad.ThreadHook(4 /*WH_CALLWNDPROC*/ , HookSendCallback, dwMainThreadID, 0x6 /*WM_SETFOCUS*/ )) {
if (hSubClass = AkelPad.WindowSubClass(hWndListBox, ListBoxCallback, 0x021 /*WM_MOUSEACTIVATE*/ ,
0x087 /*WM_GETDLGCODE*/ ,
0x100 /*WM_KEYDOWN*/ ,
0x101 /*WM_KEYUP*/ ,
0x201 /*WM_LBUTTONDOWN*/ ,
0x202 /*WM_LBUTTONUP*/ ,
0x203 /*WM_LBUTTONDBLCLK*/ )) {
//Allow other scripts running
AkelPad.ScriptNoMutex();
//Message loop
AkelPad.WindowGetMessage();
AkelPad.WindowUnsubClass(hWndListBox);
}
AkelPad.ThreadUnhook(hHookSend);
}
AkelPad.ThreadUnhook(hHookPost);
}
if (!bNoSwitch) {
i = AkelPad.SendMessage(hWndListBox, 0x188 /*LB_GETCURSEL*/ , 0, 0);
// oSys.Call("user32::PostMessage" + _TCHAR, hMainWnd, 1285 /*AKD_FRAMEACTIVATE*/ , 0, lpFrameList[i][1]);
// Редактируемый участок 1
var Pos;
var Ext;
Pos = lpFrameList[i][0].indexOf(" - ")
Ext = lpFrameList[i][0].substr(Pos + 3)
if (bAsk)
{
var mess = "";
for (i = 0; i < lpAllList.length; ++i) {
if (Ext === lpAllList[i][0])
{
mess += AkelPad.GetFilePath(lpAllList[i][2], 2) + "\n";
}
}
if (AkelPad.MessageBox(hMainWnd, mess, "Закрыть эти вкладки?", 32, 0, 1 , "&OK", 0x1 , 2 , "&Cancel", 0) == 1)
{
for (i = 0; i < lpAllList.length; ++i) {
if (Ext === lpAllList[i][0])
{
oSys.Call("user32::PostMessage" + _TCHAR, hMainWnd, 1287 /*AKD_FRAMEDESTROY*/ , 0, lpAllList[i][1]);
}
}
}
} else {
for (i = 0; i < lpAllList.length; ++i) {
if (Ext === lpAllList[i][0])
{
oSys.Call("user32::PostMessage" + _TCHAR, hMainWnd, 1287 /*AKD_FRAMEDESTROY*/ , 0, lpAllList[i][1]);
}
}
}
// Конец Редактируемый участок 1
}
//oSys.Call("user32::DestroyWindow", hWndListBox);
}
oSys.Call("user32::DestroyWindow", hWndContainer);
}
AkelPad.WindowUnregisterClass(pClassName);
}
//Release font
if (pFontName || nFontStyle || nFontSize) {
if (hFontEdit)
oSys.Call("gdi32::DeleteObject", hFontEdit);
}
} else {
if (lpFrameList.length >= 2)
oSys.Call("user32::PostMessage" + _TCHAR, hMainWnd, 1285 /*AKD_FRAMEACTIVATE*/ , 0, lpFrameList[nCurSel][1]);
}
function DialogCallback(hWnd, uMsg, wParam, lParam) {
if (uMsg == 0x021 /*WM_MOUSEACTIVATE*/ ) {
return 3 /*MA_NOACTIVATE*/ ;
} else if (uMsg == 0x2B /*WM_DRAWITEM*/ ) {
var hDC;
var hIcon;
var nItemID;
var nItemState;
var lpItem;
var rcItem = [];
var crText;
var crBk;
var hBrushBk;
var nModeBkOld;
hDC = AkelPad.MemRead(_PtrAdd(lParam, _X64 ? 32 : 24) /*offsetof(DRAWITEMSTRUCT, hDC)*/ , 2 /*DT_QWORD*/ );
nItemID = AkelPad.MemRead(_PtrAdd(lParam, _X64 ? 8 : 8) /*offsetof(DRAWITEMSTRUCT, itemID)*/ , 3 /*DT_DWORD*/ );
nItemState = AkelPad.MemRead(_PtrAdd(lParam, _X64 ? 16 : 16) /*offsetof(DRAWITEMSTRUCT, itemState)*/ , 3 /*DT_DWORD*/ );
lpItem = _PtrAdd(lParam, _X64 ? 40 : 28) /*offsetof(DRAWITEMSTRUCT, rcItem)*/ ;
RectToArray(lpItem, rcItem);
//Set background
if (nItemState & 0x1 /*ODS_SELECTED*/ ) {
crText = oSys.Call("user32::GetSysColor", 14 /*COLOR_HIGHLIGHTTEXT*/ );
crBk = oSys.Call("user32::GetSysColor", 13 /*COLOR_HIGHLIGHT*/ );
hBrushBk = oSys.Call("user32::GetSysColorBrush", 13 /*COLOR_HIGHLIGHT*/ );
} else {
crText = oSys.Call("user32::GetSysColor", 8 /*COLOR_WINDOWTEXT*/ );
crBk = oSys.Call("user32::GetSysColor", 5 /*COLOR_WINDOW*/ );
hBrushBk = oSys.Call("user32::GetSysColorBrush", 5 /*COLOR_WINDOW*/ );
}
oSys.Call("user32::FillRect", hDC, lpItem, hBrushBk);
nModeBkOld = oSys.Call("gdi32::SetBkMode", hDC, 1 /*TRANSPARENT*/ );
//Draw icon
hIcon = AkelPad.SendMessage(hMainWnd, 1223 /*AKD_GETFRAMEINFO*/ , 38 /*FI_ICONHANDLE*/ , lpFrameList[nItemID][1]);
oSys.Call("user32::DrawIconEx", hDC, rcItem.left, rcItem.top + (rcItem.bottom - rcItem.top) / 2 - nIconSize / 2, hIcon, nIconSize, nIconSize, 0, 0, 0x3 /*DI_NORMAL*/ );
//Draw text
oSys.Call("gdi32::SetTextColor", hDC, crText);
oSys.Call("gdi32::SetBkColor", hDC, crBk);
oSys.Call("gdi32::TextOut" + _TCHAR, hDC, rcItem.left + nIconSize + nIconGap, rcItem.top + (rcItem.bottom - rcItem.top) / 2 - nMaxCharHeight / 2, lpFrameList[nItemID][0], lpFrameList[nItemID][0].length);
oSys.Call("gdi32::SetBkMode", hDC, nModeBkOld);
}
return 0;
}
function HookPostCallback(nCode, wParam, lParam) {
var uMsg = AkelPad.MemRead(_PtrAdd(lParam, _X64 ? 8 : 4) /*offsetof(MSG, message)*/ , 3 /*DT_DWORD*/ );
var nParamW;
var nParamL;
if (uMsg == 0x201 /*WM_LBUTTONDOWN*/ ||
uMsg == 0x0A1 /*WM_NCLBUTTONDOWN*/ ||
uMsg == 0x204 /*WM_RBUTTONDOWN*/ ||
uMsg == 0x0A4 /*WM_NCRBUTTONDOWN*/ ||
uMsg == 0x207 /*WM_MBUTTONDOWN*/ ||
uMsg == 0x0A7 /*WM_NCMBUTTONDOWN*/ ) {
var hWnd = AkelPad.MemRead(_PtrAdd(lParam, 0) /*offsetof(MSG, hwnd)*/ , 2 /*DT_QWORD*/ );
if (hWnd != hWndListBox) {
//Not in rect
bNoSwitch = true;
//Exit message loop
oSys.Call("user32::PostQuitMessage", 0);
}
} else if (uMsg == 0x100 /*WM_KEYDOWN*/ ||
uMsg == 0x101 /*WM_KEYUP*/ ||
uMsg == 0x104 /*WM_SYSKEYDOWN*/ ||
uMsg == 0x105 /*WM_SYSKEYUP*/ ||
uMsg == 0x20A /*WM_MOUSEWHEEL*/ ) {
nParamW = AkelPad.MemRead(_PtrAdd(lParam, _X64 ? 16 : 8) /*offsetof(MSG, nParamW)*/ , 2 /*DT_QWORD*/ );
nParamL = AkelPad.MemRead(_PtrAdd(lParam, _X64 ? 24 : 12) /*offsetof(MSG, lParam)*/ , 2 /*DT_QWORD*/ );
AkelPad.SendMessage(hWndListBox, uMsg, nParamW, nParamL);
AkelPad.MemCopy(_PtrAdd(lParam, _X64 ? 8 : 4) /*offsetof(MSG, message)*/ , 0 /*WM_NULL*/ , 3 /*DT_DWORD*/ );
}
}
function HookSendCallback(nCode, wParam, lParam) {
var uMsg = AkelPad.MemRead(_PtrAdd(lParam, _X64 ? 16 : 8) /*offsetof(CWPSTRUCT, message)*/ , 3 /*DT_DWORD*/ );
var nParamW;
var nParamL;
if (uMsg == 0x6 /*WM_SETFOCUS*/ ) {
bNoSwitch = true;
//Exit message loop
oSys.Call("user32::PostQuitMessage", 0);
}
}
function ListBoxCallback(hWnd, uMsg, wParam, lParam) {
if (uMsg == 0x021 /*WM_MOUSEACTIVATE*/ ) {
return 3 /*MA_NOACTIVATE*/ ;
} else if (uMsg == 0x087 /*WM_GETDLGCODE*/ ) {
AkelPad.WindowNoNextProc(hSubClass);
return 0x4 /*DLGC_WANTALLKEYS*/ ;
} else if (uMsg == 0x100 /*WM_KEYDOWN*/ ) {
if (wParam == 0x43 /*c*/ ) {
if (bCtrlTab || (oSys.Call("user32::GetKeyState", 0x11 /*VK_CONTROL*/ ) & 0x8000)) {
i = AkelPad.SendMessage(hWndListBox, 0x188 /*LB_GETCURSEL*/ , 0, 0);
AkelPad.SetClipboardText(lpFrameList[i][0]);
}
} else if (wParam == 0x9 /*VK_TAB*/ ) {
var nCount;
nCount = AkelPad.SendMessage(hWndListBox, 0x18B /*LB_GETCOUNT*/ , 0, 0);
i = AkelPad.SendMessage(hWndListBox, 0x188 /*LB_GETCURSEL*/ , 0, 0);
if (!(oSys.Call("user32::GetKeyState", 0x10 /*VK_SHIFT*/ ) & 0x8000)) {
if (++i >= nCount)
i = 0;
} else {
if (--i < 0)
i = nCount - 1;
}
AkelPad.SendMessage(hWndListBox, 0x186 /*LB_SETCURSEL*/ , i, 0);
} else if (wParam == 0xD /*VK_RETURN*/ ) {
//Exit message loop
oSys.Call("user32::PostQuitMessage", 0);
} else if (wParam == 0x1B /*VK_ESCAPE*/ ) {
bNoSwitch = true;
//Exit message loop
oSys.Call("user32::PostQuitMessage", 0);
}
} else if (uMsg == 0x101 /*WM_KEYUP*/ ) {
if (wParam == 0x11 /*VK_CONTROL*/ ) {
if (bCtrlTab) {
//Exit message loop
oSys.Call("user32::PostQuitMessage", 0);
}
}
} else if (uMsg == 0x201 /*WM_LBUTTONDOWN*/ ) {
var lResult = AkelPad.SendMessage(hWndListBox, 0x01A9 /*LB_ITEMFROMPOINT*/ , 0, lParam);
if (HIWORD(lResult) == 0)
AkelPad.SendMessage(hWndListBox, 0x186 /*LB_SETCURSEL*/ , LOWORD(lResult), 0);
AkelPad.WindowNoNextProc(hSubClass);
} else if (uMsg == 0x202 /*WM_LBUTTONUP*/ ||
uMsg == 0x203 /*WM_LBUTTONDBLCLK*/ ) {
if (uMsg == 0x203 /*WM_LBUTTONDBLCLK*/ || bSingleClick) {
//Exit message loop
oSys.Call("user32::PostQuitMessage", 0);
}
}
}
function GetFrameList(lpFrameList, lpAllList) {
// var lpCurFrame=AkelPad.SendMessage(hMainWnd, 1288 /*AKD_FRAMEFIND*/, 1 /*FWF_CURRENT*/, 0);
var lpInitFrame;
var lpFrame;
var pNumFind;
var pStrFind = ":";
var i;
var j;
var n;
// Редактируемый участок 2
lpInitFrame = AkelPad.SendMessage(hMainWnd, 1288 /*AKD_FRAMEFIND*/ , 8 /*FWF_BYTABINDEX*/ , 0);
lpFrame = lpInitFrame;
j = -1
for (i = 0; lpFrame; ++i) {
lpAllList[i] = [0, 0];
lpAllList[i][0] = AkelPad.GetFilePath(AkelPad.MemRead(AkelPad.SendMessage(hMainWnd, 1223 /*AKD_GETFRAMEINFO*/ , 32 /*FI_FILEW*/ , lpFrame), 1 /*DT_UNICODE*/ ), 4 /*расширение*/ );
lpAllList[i][1] = lpFrame;
lpAllList[i][2] = AkelPad.MemRead(AkelPad.SendMessage(hMainWnd, 1223 /*AKD_GETFRAMEINFO*/ , 32 /*FI_FILEW*/ , lpFrame), 1 /*DT_UNICODE*/ );
// Если не найден то добавляем, иначе добавляем +1 к количеству, делая подсчёт однотипных
if (pStrFind.indexOf(":" + lpAllList[i][0] + ":") === -1) {
pStrFind += lpAllList[i][0] + ":"
j += 1
lpFrameList[j] = [0, 0];
lpFrameList[j][0] = lpAllList[i][0];
lpFrameList[j][1] = lpFrame;
// if (typeof(lpFrameList[j][2]) == "undefined") {
// lpFrameList[j][2] = 0
// }
lpFrameList[j][2] = 1;
} else {
for (n = 0; n < lpFrameList.length; ++n) {
if (lpAllList[i][0] === lpFrameList[n][0])
lpFrameList[n][2] += 1;
}
}
lpFrame = AkelPad.SendMessage(hMainWnd, 1288 /*AKD_FRAMEFIND*/ , 8 /*FWF_BYTABINDEX*/ , i + 1);
if (lpFrame == lpInitFrame) break;
}
lpFrameList.sort(SortNum) // но сортируется по первой колонке, не то что требуется
if (lpAllList.length < nMinTabs)
{
WScript.Quit();
}
// делаем ширину пунктов одинаковой, для пунктов от 1 до 9 добавляем пробел слева
for (i = 0; i < lpFrameList.length; ++i) {
if (10 > lpFrameList[i][2])
{
lpFrameList[i][0] = " " + lpFrameList[i][2] +" - " + lpFrameList[i][0];
} else {
lpFrameList[i][0] = lpFrameList[i][2] +" - " + lpFrameList[i][0];
}
}
// Конец Редактируемый участок 2
return 0;
}
function SortNum(a, b){
return b[2] - a[2];
// if(a < b)
// return -1
// if(a > b)
// return 1
// return 0
}
function CreateFont(pFaceName, nFontStyle, nPointSize) {
//Release it with: oSys.Call("gdi32::DeleteObject", hFont);
var lpLogFontSrc;
var lpLogFontDst;
var hDC;
var hFont = 0;
var nHeight;
var nWeight;
var nItalic;
if (lpLogFontDst = AkelPad.MemAlloc(92 /*sizeof(LOGFONTW)*/ )) {
lpLogFontSrc = AkelPad.SendMessage(hMainWnd, 1223 /*AKD_GETFRAMEINFO*/ , 48 /*FI_EDITFONTW*/ , 0);
oSys.Call("kernel32::RtlMoveMemory", lpLogFontDst, lpLogFontSrc, 92 /*sizeof(LOGFONTW)*/ );
if (nPointSize) {
if (hDC = oSys.Call("user32::GetDC", hMainWnd)) {
nHeight = -oSys.Call("kernel32::MulDiv", nPointSize, oSys.Call("gdi32::GetDeviceCaps", hDC, 90 /*LOGPIXELSY*/ ), 72);
AkelPad.MemCopy(_PtrAdd(lpLogFontDst, 0) /*offsetof(LOGFONTW, lfHeight)*/ , nHeight, 3 /*DT_DWORD*/ );
oSys.Call("user32::ReleaseDC", hMainWnd, hDC);
}
}
if (nFontStyle != 0 /*FS_NONE*/ ) {
nWeight = (nFontStyle == 2 /*FS_FONTBOLD*/ || nFontStyle == 4 /*FS_FONTBOLDITALIC*/ ) ? 700 /*FW_BOLD*/ : 400 /*FW_NORMAL*/ ;
AkelPad.MemCopy(_PtrAdd(lpLogFontDst, 16) /*offsetof(LOGFONTW, lfWeight)*/ , nWeight, 3 /*DT_DWORD*/ );
nItalic = (nFontStyle == 3 /*FS_FONTITALIC*/ || nFontStyle == 4 /*FS_FONTBOLDITALIC*/ ) ? 1 : 0;
AkelPad.MemCopy(_PtrAdd(lpLogFontDst, 20) /*offsetof(LOGFONTW, lfItalic)*/ , nItalic, 5 /*DT_BYTE*/ );
}
if (_TSTR == 0 /*DT_ANSI*/ && !pFaceName)
pFaceName = AkelPad.MemRead(_PtrAdd(lpLogFontDst, 28) /*offsetof(LOGFONTW, lfFaceName)*/ , 1 /*DT_UNICODE*/ );
if (pFaceName)
AkelPad.MemCopy(_PtrAdd(lpLogFontDst, 28) /*offsetof(LOGFONTW, lfFaceName)*/ , pFaceName.substr(0, 32 /*LF_FACESIZE*/ ), _TSTR);
hFont = oSys.Call("gdi32::CreateFontIndirect" + _TCHAR, lpLogFontDst);
AkelPad.MemFree(lpLogFontDst);
}
return hFont;
}
function GetCursorPos(ptPoint) {
var lpPoint;
ptPoint.x = 0;
ptPoint.y = 0;
if (lpPoint = AkelPad.MemAlloc(8 /*sizeof(POINT)*/ )) {
if (oSys.Call("user32::GetCursorPos", lpPoint)) {
ptPoint.x = AkelPad.MemRead(_PtrAdd(lpPoint, 0) /*offsetof(POINT, x)*/ , 3 /*DT_DWORD*/ );
ptPoint.y = AkelPad.MemRead(_PtrAdd(lpPoint, 4) /*offsetof(POINT, y)*/ , 3 /*DT_DWORD*/ );
}
AkelPad.MemFree(lpPoint);
}
}
function RectToArray(lpRect, rcRect) {
rcRect.left = AkelPad.MemRead(_PtrAdd(lpRect, 0) /*offsetof(RECT, left)*/ , 3 /*DT_DWORD*/ );
rcRect.top = AkelPad.MemRead(_PtrAdd(lpRect, 4) /*offsetof(RECT, top)*/ , 3 /*DT_DWORD*/ );
rcRect.right = AkelPad.MemRead(_PtrAdd(lpRect, 8) /*offsetof(RECT, right)*/ , 3 /*DT_DWORD*/ );
rcRect.bottom = AkelPad.MemRead(_PtrAdd(lpRect, 12) /*offsetof(RECT, bottom)*/ , 3 /*DT_DWORD*/ );
return rcRect;
}
function GetWindowSize(hWnd, hWndOwner, rcRect) {
var lpRect;
var bResult = false;
if (lpRect = AkelPad.MemAlloc(16 /*sizeof(RECT)*/ )) {
if (oSys.Call("user32::GetWindowRect", hWnd, lpRect)) {
RectToArray(lpRect, rcRect);
rcRect.right -= rcRect.left;
rcRect.bottom -= rcRect.top;
if (hWndOwner)
bResult = oSys.Call("user32::ScreenToClient", hWndOwner, lpRect);
else
bResult = true;
rcRect.left = AkelPad.MemRead(_PtrAdd(lpRect, 0) /*offsetof(RECT, left)*/ , 3 /*DT_DWORD*/ );
rcRect.top = AkelPad.MemRead(_PtrAdd(lpRect, 4) /*offsetof(RECT, top)*/ , 3 /*DT_DWORD*/ );
}
AkelPad.MemFree(lpRect);
}
return bResult;
}
function LOWORD(dwNumber) {
return (dwNumber & 0xffff);
}
function HIWORD(dwNumber) {
return (dwNumber >> 16);
}
function MAKELONG(a, b) {
return (a & 0xffff) | ((b & 0xffff) << 16);
}
Code: Select all
;- TOP
EnableExplicit
;- ● Global
Global bCtrlTab = #True
Global nMinTabs = 2
Global pFontName$ = "Arial"
Global nFontStyle = 0 ; ignored
Global nFontSize = 0
Global nLineGap = 1
Global bSingleClick = #False
Global ShowModify = 2
Global nWindowLeft = -1
Global nWindowTop = -1
Global nWindowMaxHeight = -1
Global nWindowMaxWidth = -1
Global bAsk = #False
Global hMainWnd ; AkelPad.Windows
Global hWndEdit ; AkelPad.Edit
Global oSys ; AkelPad.SystemFunction
Global hInstanceDLL ; AkelPad.GetInstanceDll
Global pClassName
Global hWndContainer
Global hWndListBox
Global hHookPost
Global hHookSend
Global hSubClass
Global hDC
Global hBrushHollow
Global hFontEdit
Global Dim lpFrameList.s(5, 2)
Global rcMain.RECT
Global ptPoint.POINT
Global nItemHeight
Global nScreenWidth
Global nControlWidth
Global nControlHeight
Global nMaxControlHeight
Global nCharWidth
Global nCharHeight
Global nMaxCharWidth
Global nMaxCharHeight
Global nIconSize = 16
Global nIconGap = 2
Global bNoSwitch = #False
; Structure SIZE
; cx.l
; cy.l
; EndStructure
Define nCurSel, *lpSize.SIZE, i
;- ● Declare
Declare Min(*v1.Integer, *v2.Integer)
Declare Max(*v1.Integer, *v2.Integer)
Declare ListBoxCallback(hWnd, uMsg, wParam, lParam)
Declare GetFrameList(Array lpFrameList.s(2))
Declare DialogCallback(hWnd, uMsg, wParam, lParam)
Declare GetWindowSize(hWnd, hWndOwner, *rcRect.RECT)
;-┌──GUI──┐
If OpenWindow(0, 0, 0, 320, 300, "Main", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
hMainWnd = WindowID(0)
EditorGadget(0, 8, 8, 306, 233)
hWndEdit = GadgetID(0)
EndIf
; Get list of documents
nCurSel = GetFrameList(lpFrameList())
If ArraySize(lpFrameList()) > 0
; Get font
If Asc(pFontName$) Or nFontStyle Or nFontSize
; hFontEdit = CreateFont(pFontName$, nFontStyle, nFontSize)
LoadFont(0, pFontName$, nFontSize, nFontStyle)
hFontEdit = FontID(0)
Else
hFontEdit = SendMessage_(hWndEdit, #WM_GETFONT, 0, 0)
EndIf
If Not hFontEdit
End
EndIf
; Get maximum character size
; If *lpSize = AllocateMemory(8)
If 1
If hDC = GetDC_(hWndEdit)
SelectObject_(hDC, hFontEdit)
For i = 0 To ArraySize(lpFrameList())
If GetTextExtentPoint32_(hDC, lpFrameList(i, 0), Len(lpFrameList(i, 0)), *lpSize)
; nCharWidth = PeekI(*lpSize)
nCharWidth = *lpSize\cx
; nCharHeight = PeekI(*lpSize + 4)
nCharHeight = *lpSize\cy
If nCharWidth > nMaxCharWidth
nMaxCharWidth = nCharWidth
EndIf
If nCharHeight > nMaxCharHeight
nMaxCharHeight = nCharHeight
EndIf
EndIf
Next
ReleaseDC_(hWndEdit, hDC)
EndIf
nMaxCharWidth + nIconSize + nIconGap + 16
FreeMemory(*lpSize)
EndIf
; Create dialog
; RegisterClass_(pClassName, #WM_MOUSEACTIVATE, #WM_DRAWITEM)
;-┌──GUI──┐
If OpenWindow(0, 0, 0, 220, 100, "", #PB_Window_BorderLess | #PB_Window_ScreenCentered)
SetWindowCallback(@DialogCallback())
If ListViewGadget(0, 10, 10, 250, 120, #WS_VISIBLE | #WS_CHILD | #WS_HSCROLL | #WS_VSCROLL | #WS_DLGFRAME | #LBS_OWNERDRAWFIXED)
hWndListBox = GadgetID(0) ; #LVG
; Make hWndContainer invisible
hBrushHollow = GetStockObject_(#HOLLOW_BRUSH)
SetClassLong_(hWndContainer, #GCL_HBRBACKGROUND, hBrushHollow)
SendMessage_(hWndListBox, #WM_SETFONT, hFontEdit, 1)
nItemHeight = nMaxCharHeight + nLineGap
i = SendMessage_(hWndListBox, #LB_GETITEMHEIGHT, 0, 0)
If nItemHeight < i
nItemHeight = i
Else
SendMessage_(hWndListBox, #LB_SETITEMHEIGHT, 0, nItemHeight)
EndIf
nMaxControlHeight = ArraySize(lpFrameList()) * nItemHeight + GetSystemMetrics_(#SM_CYDLGFRAME) * 2
If nWindowMaxHeight > 0
nControlHeight = Min(@nWindowMaxHeight, @nMaxControlHeight)
; If nWindowMaxHeight < nMaxControlHeight
; nControlHeight = nWindowMaxHeight
; Else
; nControlHeight = nMaxControlHeight
; EndIf
Else
nControlHeight = nMaxControlHeight
EndIf
If nControlHeight > GetSystemMetrics_(#SM_CYMAXIMIZED) - 8
nControlHeight = GetSystemMetrics_(#SM_CYMAXIMIZED) - 8
EndIf
If nWindowMaxWidth > 0
nControlWidth = Min(@nWindowMaxWidth, @nMaxCharWidth)
; If nWindowMaxWidth < nMaxCharWidth
; nControlWidth = nWindowMaxWidth
; Else
; nControlWidth = nMaxCharWidth
; EndIf
Else
nControlWidth = nMaxCharWidth
EndIf
If GetSystemMetrics_(#SM_CXMAXIMIZED) - 8 < nControlWidth
nControlWidth = GetSystemMetrics_(#SM_CXMAXIMIZED)
EndIf
If nMaxCharWidth > nControlWidth
SendMessage_(hWndListBox, #LB_SETHORIZONTALEXTENT, nMaxCharWidth, 0)
If nMaxControlHeight = nControlHeight
nControlHeight + GetSystemMetrics_(#SM_CXHSCROLL)
EndIf
EndIf
; Fill listbox
For i = 0 To ArraySize(lpFrameList())
SendMessage_(hWndListBox, #LB_ADDSTRING, 0, lpFrameList(i, 0))
Next
GetWindowSize(hMainWnd, 0, rcMain)
If nWindowLeft >= 0
rcMain\left = nWindowLeft;
ElseIf nWindowLeft = -2
GetCursorPos_(ptPoint)
rcMain\left = ptPoint\x
Else
rcMain\left + rcMain\right / 2 - nControlWidth / 2
EndIf
If Not nScreenWidth = GetSystemMetrics_(#SM_CXVIRTUALSCREEN)
nScreenWidth = GetSystemMetrics_(#SM_CXMAXIMIZED)
EndIf
rcMain\left = Min(@rcMain\left, Max((nScreenWidth - 8) - nControlWidth, 0))
If rcMain\left < 0
rcMain\left = 0
EndIf
If nWindowTop >= 0
rcMain\top = nWindowTop
ElseIf nWindowTop = -2
GetCursorPos_(ptPoint)
rcMain\top = ptPoint\y
Else
rcMain\top + rcMain\bottom / 2 - nControlHeight / 2
EndIf
rcMain\top = Min(rcMain\top, Max(GetSystemMetrics_(#SM_CYMAXIMIZED) - 8 - nControlHeight, 0))
If rcMain\top < 0
rcMain\top = 0
EndIf
SetWindowPos_(hWndContainer, 0, rcMain\left, rcMain\top, nControlWidth, nControlHeight, #SWP_NOZORDER | #SWP_NOACTIVATE)
SetWindowPos_(hWndListBox, 0, 0, 0, nControlWidth, nControlHeight, #SWP_NOMOVE | #SWP_NOZORDER | #SWP_NOACTIVATE)
SendMessage_(hWndListBox, #LB_SETCURSEL, nCurSel, 0)
ShowWindow_(hWndContainer, #SW_SHOWNOACTIVATE)
; Cause listbox is non-active, hook and send to listbox keyboard and mouse actions.
If hHookPost = AkelPad.ThreadHook(#WH_GETMESSAGE, HookPostCallback, dwMainThreadID, #WM_LBUTTONDOWN,
#WM_NCLBUTTONDOWN,
#WM_RBUTTONDOWN,
#WM_NCRBUTTONDOWN,
#WM_MBUTTONDOWN,
#WM_NCMBUTTONDOWN,
#WM_KEYDOWN,
#WM_KEYUP,
#WM_SYSKEYDOWN,
#WM_SYSKEYUP,
#WM_MOUSEWHEEL)
If hHookSend = AkelPad.ThreadHook(#WH_CALLWNDPROC, HookSendCallback, dwMainThreadID, #WM_SETFOCUS)
If hSubClass = AkelPad.WindowSubClass(hWndListBox, ListBoxCallback, #WM_MOUSEACTIVATE,
#WM_GETDLGCODE,
#WM_KEYDOWN,
#WM_KEYUP,
#WM_LBUTTONDOWN,
#WM_LBUTTONUP,
#WM_LBUTTONDBLCLK)
; Allow other scripts running
AkelPad.ScriptNoMutex()
; Message loop
AkelPad.WindowGetMessage()
AkelPad.WindowUnsubClass(hWndListBox)
EndIf
AkelPad.ThreadUnhook(hHookSend)
EndIf
AkelPad.ThreadUnhook(hHookPost)
EndIf
If Not bNoSwitch
SendMessage_(hWndListBox, #LB_GETCURSEL, 0, 0)
; Здесь ваш код обработки
EndIf
EndIf
; DestroyWindow_(hWndContainer)
CloseWindow(0)
; UnregisterClass(pClassName)
EndIf
; Release font
If pFontName$ Or nFontStyle Or nFontSize
If hFontEdit
DeleteObject_(hFontEdit)
EndIf
EndIf
Else
If ArraySize(lpFrameList()) >= 2
PostMessage_(hMainWnd, #AKD_FRAMEACTIVATE, 0, lpFrameList(nCurSel, 1))
EndIf
EndIf
Procedure Min(*v1.Integer, *v2.Integer)
If *v1\i > *v2\i
ProcedureReturn *v2\i
Else
ProcedureReturn *v1\i
EndIf
EndProcedure
Procedure Max(*v1.Integer, *v2.Integer)
If *v1\i > *v2\i
ProcedureReturn *v1\i
Else
ProcedureReturn *v2\i
EndIf
EndProcedure
Procedure DialogCallback(hWnd, uMsg, wParam, lParam)
Protected hDC, hIcon, nItemID, nItemState, *lpItem.rcItem, crText, crBk, hBrushBk, nModeBkOld
Protected item.DRAWITEMSTRUCT
; Dim rcItem(0)
Select uMsg
Case #WM_MOUSEACTIVATE
ProcedureReturn #MA_NOACTIVATE
Case #WM_DRAWITEM
hDC = item\hDC
nItemID = item\itemID
nItemState = item\itemState
*lpItem = item\rcItem
; Set background
If nItemState & #ODS_SELECTED
crText = GetSysColor_(#COLOR_HIGHLIGHTTEXT)
crBk = GetSysColor_(#COLOR_HIGHLIGHT)
hBrushBk = GetSysColorBrush_(#COLOR_HIGHLIGHT)
Else
crText = GetSysColor_(#COLOR_WINDOWTEXT)
crBk = GetSysColor_(#COLOR_WINDOW)
hBrushBk = GetSysColorBrush_(#COLOR_WINDOW)
EndIf
FillRect_(hDC, *lpItem, hBrushBk)
nModeBkOld = SetBkMode_(hDC, #TRANSPARENT)
; Draw icon
hIcon = SendMessage_(hMainWnd, #AKD_GETFRAMEINFO, #FI_ICONHANDLE, lpFrameList(nItemID, 1)) ; AKD - AkelPad
DrawIconEx_(hDC, rcItem\left, rcItem.top + (rcItem.bottom - rcItem.top) / 2 - nIconSize / 2, hIcon, nIconSize, nIconSize, 0, 0, #DI_NORMAL)
; Draw text
SetTextColor_(hDC, crText)
SetBkColor_(hDC, crBk)
TextOut_(hDC, rcItem\left + nIconSize + nIconGap, rcItem\top + (rcItem\bottom - rcItem\top) / 2 - nMaxCharHeight / 2, lpFrameList(nItemID, 0), Len(lpFrameList(nItemID, 0)))
SetBkMode_(hDC, nModeBkOld)
EndSelect
ProcedureReturn 0
EndProcedure
CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
Macro x64(x64, x86)
x86
EndMacro
CompilerElse
Macro x64(x64, x86)
x64
EndMacro
CompilerEndIf
Procedure HookPostCallback(nCode, wParam, lParam)
Protected nParamW, nParamL, uMsg.l
; Protected MSG.MSG
; uMsg = MSG\message
uMsg = PeekL(lParam + x64(8, 4))
Select uMsg
Case #WM_LBUTTONDOWN, #WM_NCLBUTTONDOWN, #WM_RBUTTONDOWN, #WM_NCRBUTTONDOWN, #WM_MBUTTONDOWN, #WM_NCMBUTTONDOWN
hWnd = PeekL(lParam)
If hWnd <> hWndListBox
; Not in rect
bNoSwitch = #True
; Exit message loop
PostQuitMessage_(0)
EndIf
Case #WM_KEYDOWN, #WM_KEYUP, #WM_SYSKEYDOWN, #WM_SYSKEYUP, #WM_MOUSEWHEEL
nParamW = PeekL(lParam+ x64(16, 8))
nParamL = PeekL(lParam+ x64(24, 12))
SendMessage_(hWndListBox, uMsg, nParamW, nParamL)
PokeL(lParam + x64(8, 4), 0)
EndSelect
EndProcedure
Procedure HookSendCallback(nCode, wParam, lParam)
Protected nParamW, nParamL, uMsg.l
; Protected CWP.CWPSTRUCT
; uMsg = CWP\message
uMsg = PeekL(lParam + x64(16, 8))
Select uMsg
Case #WM_SETFOCUS
bNoSwitch = #True
; Exit message loop
PostQuitMessage_(0)
EndSelect
EndProcedure
Procedure ListBoxCallback(hWnd, uMsg, wParam, lParam)
Protected nCount, i, bCtrlTab, hWndListBox
Select uMsg
Case #WM_MOUSEACTIVATE
ProcedureReturn #MA_NOACTIVATE
Case #WM_GETDLGCODE
; AkelPad.WindowNoNextProc(hSubClass);
ProcedureReturn #DLGC_WANTALLKEYS
Case #WM_KEYDOWN
If wParam = $43
If bCtrlTab Or GetKeyState_(#VK_CONTROL) & $8000
i = SendMessage_(hWndListBox, #LB_GETCURSEL, 0, 0)
SetClipboardText(lpFrameList(i, 0))
EndIf
ElseIf wParam = #VK_TAB
nCount = SendMessage_(hWndListBox, #LB_GETCOUNT, 0, 0)
i = SendMessage_(hWndListBox, #LB_GETCURSEL, 0, 0)
If Not GetKeyState_(#VK_SHIFT) & $8000
If(i + 1) >= nCount
i = 0
EndIf
Else
If(i - 1) < 0
i = nCount - 1
EndIf
EndIf
SendMessage_(hWndListBox, #LB_SETCURSEL, i, 0)
ElseIf wParam = #VK_RETURN
; Exit message loop
PostQuitMessage_(0)
ElseIf wParam = #VK_ESCAPE
bNoSwitch = #True
; Exit message loop
PostQuitMessage_(0)
EndIf
Case #WM_KEYUP
If wParam = #VK_CONTROL
If bCtrlTab
; Exit message loop
PostQuitMessage_(0)
EndIf
EndIf
Case #WM_LBUTTONDOWN
lResult = SendMessage_(hWndListBox, #LB_ITEMFROMPOINT, 0, lParam)
HiWord = lResult >> 16
LoWord = lResult & $FFFF
If HiWord = 0
SendMessage_(hWndListBox, #LB_SETCURSEL, LoWord, 0)
EndIf
; AkelPad.WindowNoNextProc(hSubClass)
Case #WM_LBUTTONUP
uMsg = #WM_LBUTTONDBLCLK
If uMsg = #WM_LBUTTONDBLCLK Or bSingleClick
; Exit message loop
PostQuitMessage_(0)
EndIf
EndSelect
EndProcedure
Procedure GetFrameList(Array lpFrameList.s(2))
Protected lpInitFrame, lpFrame, pNumFind, pStrFind = ":", i, j, n
ReDim lpFrameList(5, 2)
For i = 0 To 5
lpFrameList(i, 0) = "item " + Str(i)
lpFrameList(i, 1) = lpFrame
Next
ProcedureReturn 0
EndProcedure
Procedure GetWindowSize(hWnd, hWndOwner, *rcRect.RECT)
Protected *lpRect.RECT, bResult = #False
GetWindowRect_(hWnd, *lpRect)
*rcRect.right - *lpRect.left
*rcRect.bottom - *lpRect.top
If hWndOwner
bResult = ScreenToClient_(hWndOwner, *lpRect)
Else
bResult = #True
EndIf
*rcRect\left = *lpRect.left
*rcRect\top = *lpRect.top
ProcedureReturn bResult
EndProcedure
Procedure GetCursorPos(*ptPoint.POINT)
Protected lpPoint.POINT
GetCursorPos_(lpPoint)
*ptPoint\x = lpPoint\x
*ptPoint\y = lpPoint\y
EndProcedure