This commit is contained in:
Igor Pavlov
2022-01-22 18:43:09 +00:00
committed by Kornel
parent 52eeaf1ad6
commit c3529a41f5
88 changed files with 3474 additions and 435 deletions

View File

@@ -2,6 +2,8 @@
#include "StdAfx.h"
// #include "../../Windows/DLL.h"
#ifndef _UNICODE
#include "../../Common/StringConvert.h"
#endif
@@ -88,23 +90,55 @@ bool CDialog::OnButtonClicked(int buttonID, HWND /* buttonHWND */)
return true;
}
static bool GetWorkAreaRect(RECT *rect)
static bool GetWorkAreaRect(RECT *rect, HWND hwnd)
{
// use another function for multi-monitor.
if (hwnd)
{
#ifndef UNDER_CE
/* MonitorFromWindow() is supported in Win2000+
MonitorFromWindow() : retrieves a handle to the display monitor that has the
largest area of intersection with the bounding rectangle of a specified window.
dwFlags: Determines the function's return value if the window does not intersect any display monitor.
MONITOR_DEFAULTTONEAREST : Returns display that is nearest to the window.
MONITOR_DEFAULTTONULL : Returns NULL.
MONITOR_DEFAULTTOPRIMARY : Returns the primary display monitor.
*/
const HMONITOR hmon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY);
if (hmon)
{
MONITORINFO mi;
memset(&mi, 0, sizeof(mi));
mi.cbSize = sizeof(mi);
if (GetMonitorInfoA(hmon, &mi))
{
*rect = mi.rcWork;
return true;
}
}
#endif
}
/* Retrieves the size of the work area on the primary display monitor.
The work area is the portion of the screen not obscured
by the system taskbar or by application desktop toolbars.
Any DPI virtualization mode of the caller has no effect on this output. */
return BOOLToBool(::SystemParametersInfo(SPI_GETWORKAREA, 0, rect, 0));
}
bool IsDialogSizeOK(int xSize, int ySize)
bool IsDialogSizeOK(int xSize, int ySize, HWND hwnd)
{
// it returns for system font. Real font uses another values
LONG v = GetDialogBaseUnits();
int x = LOWORD(v);
int y = HIWORD(v);
const LONG v = GetDialogBaseUnits();
const int x = LOWORD(v);
const int y = HIWORD(v);
RECT rect;
GetWorkAreaRect(&rect);
int wx = RECT_SIZE_X(rect);
int wy = RECT_SIZE_Y(rect);
GetWorkAreaRect(&rect, hwnd);
const int wx = RECT_SIZE_X(rect);
const int wy = RECT_SIZE_Y(rect);
return
xSize / 4 * x <= wx &&
ySize / 8 * y <= wy;
@@ -159,47 +193,167 @@ bool CDialog::MoveItem(int id, int x, int y, int width, int height, bool repaint
return BOOLToBool(::MoveWindow(GetItem(id), x, y, width, height, BoolToBOOL(repaint)));
}
/*
typedef BOOL (WINAPI * Func_DwmGetWindowAttribute)(
HWND hwnd, DWORD dwAttribute, PVOID pvAttribute, DWORD cbAttribute);
static bool GetWindowsRect_DWM(HWND hwnd, RECT *rect)
{
// dll load and free is too slow : 300 calls in second.
NDLL::CLibrary dll;
if (!dll.Load(FTEXT("dwmapi.dll")))
return false;
Func_DwmGetWindowAttribute f = (Func_DwmGetWindowAttribute)dll.GetProc("DwmGetWindowAttribute" );
if (f)
{
#define MY__DWMWA_EXTENDED_FRAME_BOUNDS 9
// 30000 per second
RECT r;
if (f(hwnd, MY__DWMWA_EXTENDED_FRAME_BOUNDS, &r, sizeof(RECT)) == S_OK)
{
*rect = r;
return true;
}
}
return false;
}
*/
static bool IsRect_Small_Inside_Big(const RECT &sm, const RECT &big)
{
return sm.left >= big.left
&& sm.right <= big.right
&& sm.top >= big.top
&& sm.bottom <= big.bottom;
}
static bool AreRectsOverlapped(const RECT &r1, const RECT &r2)
{
return r1.left < r2.right
&& r1.right > r2.left
&& r1.top < r2.bottom
&& r1.bottom > r2.top;
}
static bool AreRectsEqual(const RECT &r1, const RECT &r2)
{
return r1.left == r2.left
&& r1.right == r2.right
&& r1.top == r2.top
&& r1.bottom == r2.bottom;
}
void CDialog::NormalizeSize(bool fullNormalize)
{
RECT workRect;
GetWorkAreaRect(&workRect);
int xSize = RECT_SIZE_X(workRect);
int ySize = RECT_SIZE_Y(workRect);
if (!GetWorkAreaRect(&workRect, *this))
return;
RECT rect;
GetWindowRect(&rect);
int xSize2 = RECT_SIZE_X(rect);
int ySize2 = RECT_SIZE_Y(rect);
bool needMove = (xSize2 > xSize || ySize2 > ySize);
if (xSize2 > xSize || (needMove && fullNormalize))
if (!GetWindowRect(&rect))
return;
int xs = RECT_SIZE_X(rect);
int ys = RECT_SIZE_Y(rect);
// we don't want to change size using workRect, if window is outside of WorkArea
if (!AreRectsOverlapped(rect, workRect))
return;
/* here rect and workRect are overlapped, but it can be false
overlapping of small shadow when window in another display. */
const int xsW = RECT_SIZE_X(workRect);
const int ysW = RECT_SIZE_Y(workRect);
if (xs <= xsW && ys <= ysW)
return; // size of window is OK
if (fullNormalize)
{
rect.left = workRect.left;
rect.right = workRect.right;
xSize2 = xSize;
}
if (ySize2 > ySize || (needMove && fullNormalize))
{
rect.top = workRect.top;
rect.bottom = workRect.bottom;
ySize2 = ySize;
}
if (needMove)
{
if (fullNormalize)
Show(SW_SHOWMAXIMIZED);
else
Move(rect.left, rect.top, xSize2, ySize2, true);
Show(SW_SHOWMAXIMIZED);
return;
}
int x = workRect.left;
int y = workRect.top;
if (xs < xsW) x += (xsW - xs) / 2; else xs = xsW;
if (ys < ysW) y += (ysW - ys) / 2; else ys = ysW;
Move(x, y, xs, ys, true);
}
void CDialog::NormalizePosition()
{
RECT workRect, rect;
GetWorkAreaRect(&workRect);
GetWindowRect(&rect);
if (rect.bottom > workRect.bottom && rect.top > workRect.top)
Move(rect.left, workRect.top, RECT_SIZE_X(rect), RECT_SIZE_Y(rect), true);
RECT workRect;
if (!GetWorkAreaRect(&workRect, *this))
return;
RECT rect2 = workRect;
bool useWorkArea = true;
const HWND parentHWND = GetParent();
if (parentHWND)
{
RECT workRectParent;
if (!GetWorkAreaRect(&workRectParent, parentHWND))
return;
// if windows are in different monitors, we use only workArea of current window
if (AreRectsEqual(workRectParent, workRect))
{
// RECT rect3; if (GetWindowsRect_DWM(parentHWND, &rect3)) {}
CWindow wnd(parentHWND);
if (wnd.GetWindowRect(&rect2))
{
// it's same monitor. So we try to use parentHWND rect.
/* we don't want to change position, if parent window is not inside work area.
In Win10 : parent window rect is 8 pixels larger for each corner than window size for shadow.
In maximize mode : window is outside of workRect.
if parent window is inside workRect, we will use parent window instead of workRect */
if (IsRect_Small_Inside_Big(rect2, workRect))
useWorkArea = false;
}
}
}
RECT rect;
if (!GetWindowRect(&rect))
return;
if (useWorkArea)
{
// we don't want to move window, if it's already inside.
if (IsRect_Small_Inside_Big(rect, workRect))
return;
// we don't want to move window, if it's outside of workArea
if (!AreRectsOverlapped(rect, workRect))
return;
rect2 = workRect;
}
{
const int xs = RECT_SIZE_X(rect);
const int ys = RECT_SIZE_Y(rect);
const int xs2 = RECT_SIZE_X(rect2);
const int ys2 = RECT_SIZE_Y(rect2);
// we don't want to change position if parent is smaller.
if (xs <= xs2 && ys <= ys2)
{
const int x = rect2.left + (xs2 - xs) / 2;
const int y = rect2.top + (ys2 - ys) / 2;
if (x != rect.left || y != rect.top)
Move(x, y, xs, ys, true);
// SetWindowPos(*this, HWND_TOP, x, y, 0, 0, SWP_NOSIZE);
return;
}
}
}
bool CModelessDialog::Create(LPCTSTR templateName, HWND parentWindow)
{
HWND aHWND = CreateDialogParam(g_hInstance, templateName, parentWindow, DialogProcedure, (LPARAM)this);

View File

@@ -183,7 +183,7 @@ public:
}
};
bool IsDialogSizeOK(int xSize, int ySize);
bool IsDialogSizeOK(int xSize, int ySize, HWND hwnd = NULL);
}}

View File

@@ -139,11 +139,6 @@ bool CFileBase::Close() throw()
return true;
}
bool CFileBase::GetPosition(UInt64 &position) const throw()
{
return Seek(0, FILE_CURRENT, position);
}
bool CFileBase::GetLength(UInt64 &length) const throw()
{
#ifdef SUPPORT_DEVICE_FILE
@@ -154,13 +149,64 @@ bool CFileBase::GetLength(UInt64 &length) const throw()
}
#endif
DWORD sizeHigh;
DWORD sizeLow = ::GetFileSize(_handle, &sizeHigh);
if (sizeLow == 0xFFFFFFFF)
DWORD high = 0;
const DWORD low = ::GetFileSize(_handle, &high);
if (low == INVALID_FILE_SIZE)
if (::GetLastError() != NO_ERROR)
return false;
length = (((UInt64)sizeHigh) << 32) + sizeLow;
length = (((UInt64)high) << 32) + low;
return true;
/*
LARGE_INTEGER fileSize;
// GetFileSizeEx() is unsupported in 98/ME/NT, and supported in Win2000+
if (!GetFileSizeEx(_handle, &fileSize))
return false;
length = (UInt64)fileSize.QuadPart;
return true;
*/
}
/* Specification for SetFilePointer():
If a new file pointer is a negative value,
{
the function fails,
the file pointer is not moved,
the code returned by GetLastError() is ERROR_NEGATIVE_SEEK.
}
If the hFile handle is opened with the FILE_FLAG_NO_BUFFERING flag set
{
an application can move the file pointer only to sector-aligned positions.
A sector-aligned position is a position that is a whole number multiple of
the volume sector size.
An application can obtain a volume sector size by calling the GetDiskFreeSpace.
}
It is not an error to set a file pointer to a position beyond the end of the file.
The size of the file does not increase until you call the SetEndOfFile, WriteFile, or WriteFileEx function.
If the return value is INVALID_SET_FILE_POINTER and if lpDistanceToMoveHigh is non-NULL,
an application must call GetLastError to determine whether or not the function has succeeded or failed.
*/
bool CFileBase::GetPosition(UInt64 &position) const throw()
{
LONG high = 0;
const DWORD low = ::SetFilePointer(_handle, 0, &high, FILE_CURRENT);
if (low == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)
{
// for error case we can set (position) to (-1) or (0) or leave (position) unchanged.
// position = (UInt64)(Int64)-1; // for debug
position = 0;
return false;
}
position = (((UInt64)(UInt32)high) << 32) + low;
return true;
// we don't want recursed GetPosition()
// return Seek(0, FILE_CURRENT, position);
}
bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const throw()
@@ -174,10 +220,18 @@ bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition
#endif
LONG high = (LONG)(distanceToMove >> 32);
DWORD low = ::SetFilePointer(_handle, (LONG)(distanceToMove & 0xFFFFFFFF), &high, moveMethod);
if (low == 0xFFFFFFFF)
if (::GetLastError() != NO_ERROR)
const DWORD low = ::SetFilePointer(_handle, (LONG)(distanceToMove & 0xFFFFFFFF), &high, moveMethod);
if (low == INVALID_SET_FILE_POINTER)
{
const DWORD lastError = ::GetLastError();
if (lastError != NO_ERROR)
{
// 21.07: we set (newPosition) to real position even after error.
GetPosition(newPosition);
SetLastError(lastError); // restore LastError
return false;
}
}
newPosition = (((UInt64)(UInt32)high) << 32) + low;
return true;
}
@@ -189,8 +243,8 @@ bool CFileBase::Seek(UInt64 position, UInt64 &newPosition) const throw()
bool CFileBase::SeekToBegin() const throw()
{
UInt64 newPosition;
return Seek(0, newPosition);
UInt64 newPosition = 0;
return Seek(0, newPosition) && (newPosition == 0);
}
bool CFileBase::SeekToEnd(UInt64 &newPosition) const throw()
@@ -531,6 +585,22 @@ bool COutFile::SetLength(UInt64 length) throw()
return SetEndOfFile();
}
bool COutFile::SetLength_KeepPosition(UInt64 length) throw()
{
UInt64 currentPos = 0;
if (!GetPosition(currentPos))
return false;
DWORD lastError = 0;
const bool result = SetLength(length);
if (!result)
lastError = GetLastError();
UInt64 currentPos2;
const bool result2 = Seek(currentPos, currentPos2);
if (lastError != 0)
SetLastError(lastError);
return (result && result2);
}
}}}
#else // _WIN32
@@ -573,7 +643,9 @@ bool CFileBase::Close()
bool CFileBase::GetLength(UInt64 &length) const
{
const off_t curPos = seek(0, SEEK_CUR);
length = 0;
// length = (UInt64)(Int64)-1; // for debug
const off_t curPos = seekToCur();
if (curPos == -1)
return false;
const off_t lengthTemp = seek(0, SEEK_END);
@@ -596,6 +668,11 @@ off_t CFileBase::seekToBegin() const throw()
return seek(0, SEEK_SET);
}
off_t CFileBase::seekToCur() const throw()
{
return seek(0, SEEK_CUR);
}
/*
bool CFileBase::SeekToBegin() const throw()
{
@@ -705,6 +782,7 @@ bool COutFile::SetLength(UInt64 length) throw()
SetLastError(EFBIG);
return false;
}
// The value of the seek pointer shall not be modified by a call to ftruncate().
int iret = ftruncate(_handle, len2);
return (iret == 0);
}

View File

@@ -247,6 +247,7 @@ public:
bool WriteFull(const void *data, size_t size) throw();
bool SetEndOfFile() throw();
bool SetLength(UInt64 length) throw();
bool SetLength_KeepPosition(UInt64 length) throw();
};
}
@@ -279,6 +280,7 @@ public:
bool GetLength(UInt64 &length) const;
off_t seek(off_t distanceToMove, int moveMethod) const;
off_t seekToBegin() const throw();
off_t seekToCur() const throw();
// bool SeekToBegin() throw();
int my_fstat(struct stat *st) const { return fstat(_handle, st); }
};
@@ -327,6 +329,10 @@ public:
}
bool SetLength(UInt64 length) throw();
bool SetLength_KeepPosition(UInt64 length) throw()
{
return SetLength(length);
}
bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw();
bool SetMTime(const FILETIME *mTime) throw();
};

View File

@@ -192,17 +192,29 @@ BSTR CPropVariant::AllocBstr(unsigned numChars)
return bstrVal;
}
#define SET_PROP_id_dest(id, dest) \
if (vt != id) { InternalClear(); vt = id; } dest = value;
void CPropVariant::Set_Int32(Int32 value) throw()
{
SET_PROP_id_dest(VT_I4, lVal);
}
void CPropVariant::Set_Int64(Int64 value) throw()
{
SET_PROP_id_dest(VT_I8, hVal.QuadPart);
}
#define SET_PROP_FUNC(type, id, dest) \
CPropVariant& CPropVariant::operator=(type value) throw() \
{ if (vt != id) { InternalClear(); vt = id; } \
dest = value; return *this; }
{ SET_PROP_id_dest(id, dest); return *this; }
SET_PROP_FUNC(Byte, VT_UI1, bVal)
// SET_PROP_FUNC(Int16, VT_I2, iVal)
SET_PROP_FUNC(Int32, VT_I4, lVal)
// SET_PROP_FUNC(Int32, VT_I4, lVal)
SET_PROP_FUNC(UInt32, VT_UI4, ulVal)
SET_PROP_FUNC(UInt64, VT_UI8, uhVal.QuadPart)
SET_PROP_FUNC(Int64, VT_I8, hVal.QuadPart)
// SET_PROP_FUNC(Int64, VT_I8, hVal.QuadPart)
SET_PROP_FUNC(const FILETIME &, VT_FILETIME, filetime)
HRESULT PropVariant_Clear(PROPVARIANT *prop) throw()

View File

@@ -45,6 +45,14 @@ inline void PropVarEm_Set_Bool(PROPVARIANT *p, bool b) throw()
class CPropVariant : public tagPROPVARIANT
{
// ---------- forbidden functions ----------
CPropVariant(const char *s);
// CPropVariant(const UString &s);
#ifdef DEBUG_FSTRING_INHERITS_ASTRING
CPropVariant(const FString &s);
CPropVariant& operator=(const FString &s);
#endif
public:
CPropVariant()
{
@@ -64,13 +72,14 @@ public:
CPropVariant(Byte value) { vt = VT_UI1; wReserved1 = 0; bVal = value; }
private:
CPropVariant(UInt16 value); // { vt = VT_UI2; wReserved1 = 0; uiVal = value; }
CPropVariant(Int16 value); // { vt = VT_I2; wReserved1 = 0; iVal = value; }
CPropVariant(Int32 value); // { vt = VT_I4; wReserved1 = 0; lVal = value; }
CPropVariant(Int64 value); // { vt = VT_I8; wReserved1 = 0; hVal.QuadPart = value; }
public:
CPropVariant(UInt32 value) { vt = VT_UI4; wReserved1 = 0; ulVal = value; }
CPropVariant(UInt64 value) { vt = VT_UI8; wReserved1 = 0; uhVal.QuadPart = value; }
CPropVariant(Int64 value) { vt = VT_I8; wReserved1 = 0; hVal.QuadPart = value; }
CPropVariant(const FILETIME &value) { vt = VT_FILETIME; wReserved1 = 0; filetime = value; }
CPropVariant& operator=(const CPropVariant &varSrc);
@@ -88,14 +97,18 @@ public:
private:
CPropVariant& operator=(Int16 value) throw();
CPropVariant& operator=(UInt16 value) throw();
CPropVariant& operator=(Int32 value) throw();
CPropVariant& operator=(Int64 value) throw();
public:
CPropVariant& operator=(Int32 value) throw();
CPropVariant& operator=(UInt32 value) throw();
CPropVariant& operator=(UInt64 value) throw();
CPropVariant& operator=(Int64 value) throw();
CPropVariant& operator=(const FILETIME &value) throw();
void Set_Int32(Int32 value) throw();
void Set_Int64(Int64 value) throw();
BSTR AllocBstr(unsigned numChars);
HRESULT Clear() throw();

View File

@@ -20,11 +20,11 @@ public:
// WRes Wait() { return Thread_Wait(&thread); }
WRes Wait_Close() { return Thread_Wait_Close(&thread); }
WRes Create(THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID param)
WRes Create(THREAD_FUNC_TYPE startAddress, LPVOID param)
{ return Thread_Create(&thread, startAddress, param); }
WRes Create_With_Affinity(THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID param, CAffinityMask affinity)
WRes Create_With_Affinity(THREAD_FUNC_TYPE startAddress, LPVOID param, CAffinityMask affinity)
{ return Thread_Create_With_Affinity(&thread, startAddress, param, affinity); }
WRes Create_With_CpuSet(THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID param, const CCpuSet *cpuSet)
WRes Create_With_CpuSet(THREAD_FUNC_TYPE startAddress, LPVOID param, const CCpuSet *cpuSet)
{ return Thread_Create_With_CpuSet(&thread, startAddress, param, cpuSet); }
#ifdef _WIN32