unit InControlUtils;

interface
uses
	Windows, Graphics, Controls, Types, SysUtils, Forms,
	ComCtrls, StdCtrls;

	{Показывает сообщение.[brd]}
	procedure ShowMessageBox(const aMessage: String; aFlags: Longint = MB_OK);
{Запрос на подтверждение.[brd]}
	function Confirm(const aQuestion: String): Boolean;
	function ConfirmWnd(aParentWnd: HWND; const aQuestion: String): Boolean;
{Показывает диалог с информацией и кнопками Ok & Cancel.[brd]}
	function ShowInformation(const anInfo: String): Boolean;

	// Гарантирует наличие и совпадение ItemFocused и Selected в aListView, если список непустой
	procedure AdjustListViewSelection(aListView: TListView);
	procedure ListView_AdjustColWidths(aListView: TListView; aTestAllItems: Boolean = True);
	procedure ListView_SetCheck(aListView: TListView; aValue: Boolean);
	function ListView_HasChecked(aListView: TListView): Boolean;

	function GetControlLT(aControl: TControl): string;
	procedure SetControlLT(aControl: TControl; const s: string; aScreenAdjust: Boolean);
	function GetControlLTWH(aControl: TControl): string;
	procedure SetControlLTWH(aControl: TControl; const s: string; aScreenAdjust: Boolean);
	function  GetFormLTWH(aForm: TCustomForm): string;
	procedure SetFormLTWH(aForm: TForm; const aParams: string; aScreenAdjust: Boolean);
	procedure SetFormLT(aForm: TForm; const aParams: string; aScreenAdjust: Boolean);

	procedure AdjustControlToScreen(aControl: TControl);

	function GetDesktopWorkArea: TRect;

	{	Перемещение элементов управления с одного окна на другое [Власов] }
	procedure MoveControls(aSrc, aDst: TWinControl);

	procedure EnableControls(const aControls: array of TControl; anEnable: Boolean = True);



implementation

uses InSysUtils, Math;

procedure ShowMessageBox(const aMessage: String; aFlags: Longint = MB_OK);
var
	aSavedCursor: TCursor;
begin
	aSavedCursor := Screen.Cursor;

	Screen.Cursor := crDefault;
	Application.MessageBox(PChar(aMessage), PChar(Application.Title), aFlags);
	Screen.Cursor := aSavedCursor;
end;

function Confirm(const aQuestion: String): Boolean;
var
	savedCursor: TCursor;
begin
	savedCursor := Screen.Cursor;
	Screen.Cursor := crDefault;
	Result := Application.MessageBox(PChar(aQuestion), PChar(Application.Title),
		MB_YESNO or MB_ICONQUESTION) = IDYES;
	Screen.Cursor := savedCursor;
end;

function ConfirmWnd(aParentWnd: HWND; const aQuestion: String): Boolean;
var
	savedCursor: TCursor;
begin
	savedCursor := Screen.Cursor;
	Screen.Cursor := crDefault;
	Result := MessageBox(aParentWnd, PChar(aQuestion), PChar(Application.Title),
		MB_YESNO or MB_ICONQUESTION) = IDYES;
	Screen.Cursor := savedCursor;
end;

function ShowInformation(const anInfo: String): Boolean;
var
	savedCursor: TCursor;
begin
	savedCursor := Screen.Cursor;
	Screen.Cursor := crDefault;
	Result := Application.MessageBox(PChar(anInfo), PChar(Application.Title),
		MB_OKCANCEL or MB_ICONINFORMATION) = IDOK;
	Screen.Cursor := savedCursor;
end;

procedure AdjustListViewSelection(aListView: TListView);
begin
	if aListView.Items.Count > 0 then begin
		if not Assigned(aListView.ItemFocused) then
			aListView.ItemFocused := aListView.Items[0];
		aListView.Selected := aListView.ItemFocused;
	end;
end;

procedure ListView_AdjustColWidths(aListView: TListView; aTestAllItems: Boolean);
var
	aMaxWidths: array of Integer;
	aListItem: TListItem;
	i, j, i1, i2: Integer;
	aMinColWidth, aMaxColWidth,
	aColWidth, aMaxTextWidth: Integer;
begin
	if aListView.Columns.Count > 0 then begin
		SetLength(aMaxWidths, aListView.Columns.Count);
		for j := 0 to Length(aMaxWidths) - 1 do
			aMaxWidths[j] := aListView.Canvas.TextWidth(aListView.Columns[j].Caption) + 28;

		if aTestAllItems then begin
			i1 := 0;
			i2 := aListView.Items.Count - 1
		end
		else begin
			i1 := aListView.TopItem.Index;
			i2 := min(i1 + aListView.VisibleRowCount, aListView.Items.Count) - 1;
		end;

		for i := i1 to i2 do begin
			aListItem := aListView.Items[i];
			aMaxWidths[0] := Max(aMaxWidths[0], aListView.Canvas.TextWidth(aListItem.Caption) + 28);
			for j := 0 to Min(Length(aMaxWidths) - 2, aListItem.SubItems.Count - 1) do
				aMaxWidths[j + 1] := Max(aMaxWidths[j + 1], aListView.Canvas.TextWidth(aListItem.SubItems[j]) + 28);
		end;

		for j := 0 to Length(aMaxWidths) - 1 do begin
			aMaxTextWidth := aMaxWidths[j];
			aMinColWidth := aListView.Columns[j].MinWidth;
			aMaxColWidth := aListView.Columns[j].MaxWidth;

			if aMaxTextWidth < aMinColWidth then
				aColWidth := aMinColWidth
			else if (aMaxColWidth > 0) and (aMaxTextWidth > aMaxColWidth) then
				aColWidth := aMaxColWidth
			else
				aColWidth := aMaxTextWidth;

			aListView.Columns[j].Width := aColWidth;
		end
	end;
end;

procedure ListView_SetCheck(aListView: TListView; aValue: Boolean);
var
	i: Integer;
begin
	if aListView.Items.Count > 0 then begin
		aListView.Items.BeginUpdate;
		try
			for i := 0 to aListView.Items.Count - 1 do
				aListView.Items[i].Checked := aValue;
		finally
			aListView.Items.EndUpdate;
		end;
	end;
end;

function ListView_HasChecked(aListView: TListView): Boolean;
var
	i: Integer;
begin
	Result := True;
	for i := 0 to aListView.Items.Count - 1 do
		if aListView.Items[i].Checked then
			Exit;

	Result := False;
end;

function GetControlLT(aControl: TControl): string;
begin
	FmtStr(Result, '%d %d', [aControl.Left, aControl.Top]);
end;

procedure SetControlLT(aControl: TControl; const s: string; aScreenAdjust: Boolean);
var
	aPos, aVal: Longint;
begin
	aPos := 1;
	if ScanLong(s, aPos, aVal) then begin
		aControl.Left := aVal;
		if ScanLong(s, aPos, aVal) then
			aControl.Top := aVal;
	end;

	if aScreenAdjust then
		AdjustControlToScreen(aControl);
end;

function GetControlLTWH(aControl: TControl): string;
begin
	FmtStr(Result, '%d %d %d %d', [aControl.Left, aControl.Top, aControl.Width, aControl.Height]);
end;

procedure SetControlLTWH(aControl: TControl; const s: string; aScreenAdjust: Boolean);
var
	aPos, aVal: Longint;
begin
	aPos := 1;
	if ScanLong(s, aPos, aVal) then begin
		aControl.Left := aVal;
		if ScanLong(s, aPos, aVal) then begin
			aControl.Top := aVal;
			if ScanLong(s, aPos, aVal) then begin
				aControl.Width := aVal;
				if ScanLong(s, aPos, aVal) then
					aControl.Height := aVal;
			end;
		end;
	end;

	if aScreenAdjust then
		AdjustControlToScreen(aControl);
end;

const
	WindowStateStrings: array[TWindowState] of string = ('normal', 'minimized', 'maximized');

function  GetFormLTWH(aForm: TCustomForm): string;
begin
	FmtStr(Result, '%d %d %d %d %s',
		[aForm.Left,
		 aForm.Top,
		 aForm.Width,
		 aForm.Height,
		 WindowStateStrings[aForm.WindowState]]);
end;

procedure SetFormLTWH(aForm: TForm; const aParams: string; aScreenAdjust: Boolean);
var
	aPos: Longint;
	aLeft, aTop, aWidth, aHeight: Longint;
	aWindowState: TWindowState;
	aWindowStateString: string;
begin
	aPos := 1;
	if ScanLong(aParams, aPos, aLeft) and ScanLong(aParams, aPos, aTop)	and
		ScanLong(aParams, aPos, aWidth) and ScanLong(aParams, aPos, aHeight)
	then begin
		aWindowStateString := Trim(Copy(aParams, aPos, Length(aParams) - aPos + 1));

		if WindowStateStrings[wsMinimized] = aWindowStateString then
			aWindowState := wsMinimized
		else if WindowStateStrings[wsMaximized] = aWindowStateString then
			aWindowState := wsMaximized
		else
			aWindowState := wsNormal;

		aForm.Position := poDesigned;
		aForm.Left := aLeft;
		aForm.Top := aTop;
		aForm.Width := aWidth;
		aForm.Height := aHeight;
		aForm.WindowState := aWindowState;

		if aScreenAdjust then
			AdjustControlToScreen(aForm);

		aForm.Realign;
	end;
end;

procedure SetFormLT(aForm: TForm; const aParams: string; aScreenAdjust: Boolean);
var
	aPos: Longint;
	aLeft, aTop, aWidth, aHeight: Longint;
	aWindowState: TWindowState;
	aWindowStateString: string;
begin
	aPos := 1;
	if ScanLong(aParams, aPos, aLeft) and ScanLong(aParams, aPos, aTop)	and
		ScanLong(aParams, aPos, aWidth) and ScanLong(aParams, aPos, aHeight)
	then begin
		aWindowStateString := Trim(Copy(aParams, aPos, Length(aParams) - aPos + 1));

		if WindowStateStrings[wsMinimized] = aWindowStateString then
			aWindowState := wsMinimized
		else if WindowStateStrings[wsMaximized] = aWindowStateString then
			aWindowState := wsMaximized
		else
			aWindowState := wsNormal;

		aForm.Position := poDesigned;
		aForm.Left := aLeft;
		aForm.Top := aTop;
		aForm.WindowState := aWindowState;

		if aScreenAdjust then
			AdjustControlToScreen(aForm);

		aForm.Realign;
	end;
end;

function GetDesktopWorkArea: TRect;
begin
	if not SystemParametersInfo(SPI_GETWORKAREA, 0, @Result, 0) then
		Result := Rect(0, 0, Screen.Width-1, Screen.Height-1);
end;

procedure AdjustControlToScreen(aControl: TControl);
var
	r: TRect;
begin
	r := GetDesktopWorkArea;

	if aControl.Left < r.Left then
		aControl.Left := r.Left
	else if aControl.Left+aControl.Width > r.Right then
		aControl.Left := Max(r.Right-aControl.Width, r.Left);

	if aControl.Top < r.Top then
		aControl.Top := r.Top
	else if aControl.Top+aControl.Height > r.Bottom then
		aControl.Top := Max(r.Bottom-aControl.Height, r.Top);
end;

procedure MoveControls(aSrc, aDst: TWinControl);
var
	aControl: TControl;
begin
	while aSrc.ControlCount > 0 do begin
		aControl := aSrc.Controls[0];
		aControl.Parent := aDst;
		aControl.Show;
	end;
end;

procedure EnableControls(const aControls: array of TControl; anEnable: Boolean);
var
	i: Integer;
	aControl: TControl;
begin
	for i := 0 to Length(aControls) - 1 do begin
		aControl := aControls[i];
		aControl.Enabled := anEnable;
		if aControl is TEdit then
			if anEnable then begin
				(aControl as TEdit).Color := clWindow;
				(aControl as TEdit).Font.Color := clWindowText;
			end
			else begin
				(aControl as TEdit).Color := clBtnFace;
				(aControl as TEdit).Font.Color := clBtnShadow;
			end;
	end
end;


end.
