• 15 апреля стартует «Курс «SQL-injection Master» ©» от команды The Codeby

    За 3 месяца вы пройдете путь от начальных навыков работы с SQL-запросами к базам данных до продвинутых техник. Научитесь находить уязвимости связанные с базами данных, и внедрять произвольный SQL-код в уязвимые приложения.

    На последнюю неделю приходится экзамен, где нужно будет показать свои навыки, взломав ряд уязвимых учебных сайтов, и добыть флаги. Успешно сдавшие экзамен получат сертификат.

    Запись на курс до 25 апреля. Получить промодоступ ...

Мигающая Иконка В Tab У Tabcontrol

  • Автор темы Shouldercannon
  • Дата начала
S

Shouldercannon

Как такое сделать одной или нескольким вкладкам, а затем вернуть исходную картинку?
 

Вложения

  • Animate.gif
    Animate.gif
    3,8 КБ · Просмотры: 516
S

sinkopa

Как такое сделать одной или нескольким вкладкам, а затем вернуть исходную картинку?
Охх... Не люблю я, если честно таб-контрол... уж больно он примитивный.
Но если так уж надо...
В общем идея состоит в следующем:
Динамически переназначать индексы картинок на Табах, после чего вызывать UpdateTabImages;
Только вот проблема в том, что метод TTabControl.UpdateTabImages находится в секции protected, т.е. из кода программы недоступен.
Поэтому без наследования не обойтись...
Дальше, надо чтобы "кто-то" (с периодичной настойчивостью) эти индексы собственно подменял.
Можно конечно это делать по таймеру, но я решил реализовать через поток (чтобы меньше "грузило").
Короче вот:
Код:
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, ImgList, StdCtrls, Spin;

const
WM_ALARM_MSG = WM_USER + 28;

type
{ Поток, который будет управлять "морганием"
сменой индекса картинки для указанной закладки
}
TAlarmer = class (TThread)
private
FTabIndex: Integer;
FAlarmCount: Integer;
FControl: HWND;
protected
procedure Execute; override;
public
constructor Create(ControlWin: HWND; TabIndex: Integer; AlarmCount: Integer = 6);
end;

type
{ Хак наследования TTabControl, чтобы "достучаться" до GetImageIndex
и UpdateTabImages; потому как они в секции protected
}
TTabControl = class(ComCtrls.TTabControl)
private
FAlarm: Boolean;
FAlarmTabIndex: Integer; // TabIndex который будет "моргать"
FAlarmImgIndex: Integer; // ImageIndex для "моргания"
protected
{ Перекрытый метод protected ComCtrls.TTabControl }
function GetImageIndex(TabIndex: Integer): Integer; override;
{ Наш слушальщик сообщений Alarmer-ра }
procedure WMAlarmMSG(var Msg: TMessage); message WM_ALARM_MSG;
end;

type
TForm1 = class(TForm)
TabControl1: TTabControl;
ImageList1: TImageList;
SpinEdit1: TSpinEdit;
Button1: TButton;
Label1: TLabel;
Label2: TLabel;
SpinEdit2: TSpinEdit;
procedure TabControl1GetImageIndex(Sender: TObject; TabIndex: Integer;
var ImageIndex: Integer);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

{ TAlarmer }

constructor TAlarmer.Create(ControlWin: HWND; TabIndex: Integer; AlarmCount: Integer);
begin
inherited Create (True);
FreeOnTerminate := True;  // после завершения, должен самостоятельно "умереть"
FControl := ControlWin;	// Хэндл окна TTabControl, куда "моргать" картинками
FTabIndex := TabIndex;	 // Индекс закладки в которой "моргать"
FAlarmCount := AlarmCount; // Количество "морганий"
Resume;
end;

procedure TAlarmer.Execute;
var
i: Integer;
begin
while (not Terminated) and (FAlarmCount > 0) do
begin
for i := 0 to 10 do
begin
Sleep(50);
if Terminated then Break; // проверяем чаще чем тикаем (А вдруг нас уже похоронили? :-)
end;
if Terminated then Break;
{ Получается два тика в секунду... }
SendMessage(FControl,WM_ALARM_MSG,FTabIndex,(FAlarmCount mod 2 + 1));
dec(FAlarmCount);
end;
{ В конце восстанавливаем "родной" ImageIndex }
SendMessage(FControl,WM_ALARM_MSG,FTabIndex,0);
end;


{ TTabControl }

function TTabControl.GetImageIndex(TabIndex: Integer): Integer;
begin
{ если Alarm - берем Alarm-мовый индекс картинки, иначе берем "родной" }
if FAlarm and (TabIndex = FAlarmTabIndex) then
Result := FAlarmImgIndex
else
Result := inherited GetImageIndex(TabIndex);
end;

procedure TTabControl.WMAlarmMSG(var Msg: TMessage);
begin
if (Msg.Msg = WM_ALARM_MSG) then
begin
FAlarmTabIndex := Msg.WParam;
FAlarmImgIndex := GetImageIndex(FAlarmTabIndex) + Msg.LParam;
FAlarm := True;
UpdateTabImages;
FAlarm := False;
FAlarmTabIndex := -1;
FAlarmImgIndex := -1;
end;
end;

{ TForm1 }

procedure TForm1.TabControl1GetImageIndex(Sender: TObject;
TabIndex: Integer; var ImageIndex: Integer);
begin
{ Назеначаем "Родные" индексы картинок на закладках }
case TabIndex of
0: ImageIndex := 2;
1: ImageIndex := 5;
2: ImageIndex := -1;
else
ImageIndex := -1;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
{ Можно не делать переменную, потому как после того как поток
создается с параметром FreeOnTerminate := True; т.е. освободит
память самостоятельно }

TAlarmer.Create(TabControl1.Handle,SpinEdit1.Value, SpinEdit2.Value);
end;

end.
Не утверждаю, что это законченное решение... но в качестве наброска надеюсь сгодится... :)
Сам проект в аттаче
Посмотреть вложение TabImageTimer.rar
 
S

Shouldercannon

Данный способ хорошо работает для одной вкладки. Если нужно сразу на многих делать мигание, то поток начинает тупить. Прям массив таймеров создавай. Так же нужно, чтобы иконка мигала до тех пор пока не будет осуществлён переход на вкладку, тоесть количество миганий безлимитное.
 
S

sinkopa

Данный способ хорошо работает для одной вкладки. Если нужно сразу на многих делать мигание, то поток начинает тупить.
А я не обещал что ничего тупить не будет (собственно Вы и не просили) ... :(
Прям массив таймеров создавай. Так же нужно, чтобы иконка мигала до тех пор пока не будет осуществлён переход на вкладку, тоесть количество миганий безлимитное.
Не надо массивов никаких...
Четко сформулированное техническое задание - снижает трудозатраты... :)
Код:
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, ImgList, StdCtrls;

const
WM_ALARM_MSG = WM_USER + 28; // пользовательское сообщение

type
TAlarms = array of Boolean;

type
{ Поток, который будет управлять "морганием"
}
TAlarmer = class (TThread)
private
FControl: HWND;
protected
procedure Execute; override;
public
constructor Create(ControlWin: HWND);
end;

type
{ Хак наследования TTabControl, чтобы "достучаться" к UpdateTabImages;
потому как он в секции protected
}
TTabControl = class(ComCtrls.TTabControl)
private
FEvenAlarm: Boolean;  // флаг - показывает четный или нечетный тик
protected
{ слушальщик сообщений Alarmer-ра }
procedure WMAlarmMSG(var Msg: TMessage); message WM_ALARM_MSG;
public
Alarm: TAlarms; // массив булиновых флагов (выставить длину по количеству Табов)
end;

type
TForm1 = class(TForm)
TabControl1: TTabControl;
ImageList1: TImageList;
Button1: TButton;
Button2: TButton;
CheckBox1: TCheckBox;
CheckBox2: TCheckBox;
CheckBox3: TCheckBox;
procedure TabControl1GetImageIndex(Sender: TObject; TabIndex: Integer;
var ImageIndex: Integer);
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure CheckBox1Click(Sender: TObject);
procedure CheckBox2Click(Sender: TObject);
procedure CheckBox3Click(Sender: TObject);
private
{ Private declarations }
Alarmer : TAlarmer;	 // поток - алармер
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

{ TAlarmer }

constructor TAlarmer.Create(ControlWin: HWND);
begin
inherited Create (True);
FreeOnTerminate := False;  // после завершения, должен быть удален вручную !
FControl := ControlWin;	// Хэндл окна TTabControl, куда "моргать" картинками
Resume;
end;

procedure TAlarmer.Execute;
var
i: Integer;
begin
while (not Terminated) do
begin
for i := 0 to 10 do
begin
Sleep(50);
if Terminated then Break; // проверяем чаще чем тикаем (А вдруг нас уже похоронили? :-)
end;
if Terminated then Break;
{ Получается два тика в секунду... }
PostMessage(FControl,WM_ALARM_MSG,1,0);
end;
{ В конце сбрасываем состояния "алармов" }
SendMessage(FControl,WM_ALARM_MSG,0,0);
end;


{ TTabControl }

procedure TTabControl.WMAlarmMSG(var Msg: TMessage);
var
i: Integer;
begin
if (Msg.Msg = WM_ALARM_MSG) and Visible then
begin
if (Msg.WParam > 0) then // штатный тик алармера
begin
FEvenAlarm := not FEvenAlarm;
UpdateTabImages;
end
else
begin // сброс алармов
for i := Low(Alarm) to High(Alarm) do
Alarm[i] := False;
UpdateTabImages;
end;
end;
end;

{ TForm1 }


procedure TForm1.FormCreate(Sender: TObject);
begin
Alarmer := nil;
with TabControl1 do
begin
SetLength(Alarm,Tabs.Count);
if (Tabs.Count > 0) then // начальное состояние всех элементов - False
ZeroMemory(@Alarm[0],Length(Alarm));
end;
end;

procedure TForm1.TabControl1GetImageIndex(Sender: TObject;
TabIndex: Integer; var ImageIndex: Integer);
var
Alarms : TAlarms;
EvenAlarm : Boolean;
begin
case TabIndex of
0: ImageIndex := 2;
1: ImageIndex := 5;
2: ImageIndex := -1;
else
ImageIndex := -1;
end;

with (Sender as TTabControl) do
begin
Alarms := Alarm;
EvenAlarm := FEvenAlarm;
end;

if (TabIndex < Length(Alarms)) and (Alarms[TabIndex]) then { and (TabIndex in [0..2]) }
begin
if EvenAlarm then
Inc(ImageIndex,1)
else
Inc(ImageIndex,2)
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
if not Assigned(Alarmer) then
Alarmer := TAlarmer.Create(TabControl1.Handle);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
if Assigned(Alarmer) then
begin
{Завер}
Alarmer.Terminate;	  // завершаем поток
Alarmer.WaitFor;		 // ожидание фактического! завершения потока
FreeAndNil(Alarmer);	 // уничножаем поток как объект
end;
CheckBox1.Checked := False;
CheckBox2.Checked := False;
CheckBox3.Checked := False;
end;

procedure TForm1.CheckBox1Click(Sender: TObject);
begin
TabControl1.Alarm[0] := CheckBox1.Checked;
end;

procedure TForm1.CheckBox2Click(Sender: TObject);
begin
TabControl1.Alarm[1] := CheckBox2.Checked;
end;

procedure TForm1.CheckBox3Click(Sender: TObject);
begin
TabControl1.Alarm[2] := CheckBox3.Checked;
end;

end.

Со сбросом булина, по переход на вкладку, справитесь надеюсть? :)
Посмотреть вложение TabImageTimer2.rar
 
S

Shouldercannon

1. Под сомнением. При таком количестве картинок данный код будет таким? Тест показал, что всё нормально.
Код:
procedure TForm1.TabControl1GetImageIndex(Sender: TObject;
TabIndex: Integer; var ImageIndex: Integer);
var
Alarms: TAlarms;
EvenAlarm: Boolean;
begin
{case TabIndex of
0: ImageIndex := 2;
1: ImageIndex := 5;
2: ImageIndex := -1;
else
ImageIndex := -1;
end;}

ImageIndex := 0;

with (Sender as TTabControl) do
begin
Alarms := Alarm;
EvenAlarm := FEvenAlarm;
end;

if (TabIndex < Length(Alarms)) and (Alarms[TabIndex]) then {and (TabIndex in [0..2])}
begin
if EvenAlarm then Inc(ImageIndex, 1) else Inc(ImageIndex, 2);
end;
end;
Иконка 0 - основная для вкладки (default)
Иконки 1 - 2 - мигание

2. Добавление новых вкладок и удаление старых не отразится ли негативно на вашем коде?
 

Вложения

  • img.gif
    img.gif
    15,6 КБ · Просмотры: 429
S

sinkopa

1. Под сомнением. При таком количестве картинок данный код будет таким? Тест показал, что всё нормально.
Иконка 0 - основная для вкладки (default) Иконки 1 - 2 - мигание
2. Добавление новых вкладок и удаление старых не отразится ли негативно на вашем коде?
Хм... как доктор, ответственно заявляю, что всё у Вас в порядке и тест не врёт... B)
Единстенное что (лично у меня) вызывает сомнение, так это - надо ли именно TTabControl использовать в данном конкретном случае...
Не проверял, но мне кажется, что при достаточно большом количестве вкладок должно наблюдаться легкое "помаргивание" на отрисовке контрола...
Я лично бы выблал что нибудь, на чем можно реально "рисовать"... т.е. чтобы не весь контрол перерисовывать, а только участок (вкладку) где нужно "поморгать" иконкой...
но... это дело вкуса... :mellow:
 
S

Shouldercannon

Первые косяки с внедрением кода.
Длина Массива булиновых флагов устанавлиевается один раз и это происходит в FormCreate. У меня изначально нет вкладок, значит данный способ не подходит. Значит в событии добавления/удаления вкладки на TabControl делаем следующее
Код:
 Alarmer := nil;

with TabControl1 do
begin
SetLength(Alarm, Tabs.Count);
// Начальное состояние всех элементов - False
if (Tabs.Count > 0) then ZeroMemory(@Alarm[0], Length(Alarm));
end;
Но тогда у нас перестанут мигать иконки на вкладках. Какой-то замкнутый круг получается.
 
M

-master-

Зачем этот массив? у вас данные о том что нужны вкладки откуда берутся? флаги (если они ваще нужны) надо держать вместе с данными
 
S

Shouldercannon

Есть TabControl и его тень ввиде массива
Код:
type
TTabsData = record
Nick: string;
IP: string;
TempMessage: string;
TabIndex: Integer;
end;

TabsDataArr = array of TTabsData;
...
var
FormPrivate: TFormPrivate;
TD: TabsDataArr;

function DeleteEl(TD: TabsDataArr; Index: Integer): TabsDataArr;
Так я добавляю вкладки
PHP:
procedure TFormPrivate.AddTab(Nick, IP: string; ChangeTab, ShowForm: Boolean);
var
i: Integer;
B: Boolean; // Создать новую вкладку (True - да, False - нет)
begin
B := False; // Чтобы изначально не создавать вторую вкладку после самой первой
// Добавляем самую первую вкладку
if TabControl1.Tabs.Count = 0 then
begin
i := High(TD) + 2;
SetLength(TD, i);
TD[i - 1].Nick := Nick;
TD[i - 1].IP := IP;
TD[i - 1].TempMessage := '';
TD[i - 1].TabIndex := 0;

TabControl1.Tabs.Add(Nick);
LName.Caption := Nick;
LIP.Caption := IP;
// Загрузим историю переписки приватного чата
LoadHistory(IP);
end
else
begin
// Ищем IP-адрес в массиве
for i := 0 to Length(TD) - 1 do
begin
B := False;
// Если найден нужный IP-адрес
if TD[i].IP = IP then
begin
if ChangeTab then
begin
// Сохраняем данные из текущей вкладки
TD[TabControl1.TabIndex].TempMessage := GetSendText(RVEMessage);

LName.Caption := TD[i].Nick;
LIP.Caption := TD[i].IP;
TabControl1.TabIndex := i; // Перейдём на вкладку
// Очищаем RVEMessage
RVEMessage.Clear;
ChatAddWithSmilesToEdit(RVEMessage, TD[i].TempMessage);
RVEMessage.Format;
SendTextChange(Self);
// Переводим каретку в конец сообщения
RVEMessage.SelectAll;
RVEMessage.Deselect;

// Загрузим историю переписки приватного чата
LoadHistory(TD[i].IP);
Break;
end
else
begin
// Если IP-адрес из массива совпадает с IP-адресом на вкладке
if TD[i].IP = LIP.Caption then
begin
LoadHistory(TD[i].IP);
Break;
end;
end;

Break;
end
else B := True;
end;
end;

if B then
begin
// Добавляем новую вкладку
i := High(TD) + 2;
SetLength(TD, i);
TD[i - 1].Nick := Nick;
TD[i - 1].IP := IP;
TD[i - 1].TempMessage := '';
TD[i - 1].TabIndex := TabControl1.Tabs.Count; // Задаём индекс без "- 1"

TabControl1.Tabs.Add(Nick);

if ChangeTab then
begin
// Сохраняем данные из текущей вкладки
TD[TabControl1.TabIndex].TempMessage := GetSendText(RVEMessage);

LName.Caption := Nick;
LIP.Caption := IP;
TabControl1.TabIndex := TabControl1.Tabs.Count - 1; // Перейдём на вкладку
// Очищаем RVEMessage
RVEMessage.Clear;
RVEMessage.Format;
SendTextChange(Self);
// Загрузим историю переписки приватного чата
LoadHistory(IP);
end;
end;

if ShowForm then
begin
ShowAs;
RVEMessage.SetFocus;
end;
end;
Так удаляю
Код:
procedure TFormPrivate.TBCloseChatClick(Sender: TObject);
var
i, i2: Integer;
begin
if TabControl1.Tabs.Count > 1 then
begin
i := TabControl1.TabIndex - 1; // Вкладка левее
if i < 1 then i := 0;

// Ищем IP-адрес в массиве
for i2 := 0 to Length(TD) - 1 do
begin
if TD[i2].IP = LIP.Caption then
begin
SetLength(TD, Length(TD)); // Задаём новую длину
TD := DeleteEl(TD, i2); // Удаляем найденную секцию при этом индексы вкладок остаются старые
Break;
end;
end;

TabControl1.Tabs.Delete(TabControl1.TabIndex);
TabControl1.TabIndex := i; // Перейдём на вкладку

// Переназначим индексы у вкладок после удаления элемента из массива
for i := 0 to Length(TD) - 1 do
begin
TD[i].TabIndex := i;
end;

TabControl1.OnChange(Self);
end
else
begin
TabControl1.Tabs.Delete(TabControl1.TabIndex);
SetLength(TD, 0);
SLSenders.Clear;

// Нет вклдок, нет и оповещений
CoolTrayIcon1.IconVisible := False;
CoolTrayIcon1.CycleIcons := False;

// Очищаем RVEMessage
RVEMessage.Clear;
RVEMessage.Format;
SendTextChange(Sender);
RVEMessage.SetFocus;

Close;
end;
end;
Так загружаю данные для вкладки
Код:
procedure TFormPrivate.TabControl1Change(Sender: TObject);
var
i: Integer;
begin
for i := 0 to Length(TD) - 1 do
begin
if TabControl1.TabIndex = TD[i].TabIndex then
begin
LName.Caption := TD[i].Nick;
LIP.Caption := TD[i].IP;
TabControl1.TabIndex := i; // Перейдём на вкладку
DeleteSender(TD[i].IP, False, True);

// Очищаем RVEMessage
RVEMessage.Clear;
ChatAddWithSmilesToEdit(RVEMessage, TD[i].TempMessage);
RVEMessage.Format;
SendTextChange(Sender);
// Переводим каретку в конец сообщения
RVEMessage.SelectAll;
RVEMessage.Deselect;

// Загрузим историю переписки приватного чата
LoadHistory(TD[i].IP);

Break;
end;
end;
end;
Так забираю сообщени из поля ввода
Код:
procedure TFormPrivate.TabControl1Changing(Sender: TObject;
var AllowChange: Boolean);
begin
// Сохраняем данные из текущей вкладки
TD[TabControl1.TabIndex].TempMessage := GetSendText(RVEMessage);
end;
Так удаляю из массива секцию
Код:
function DeleteEl(TD: TabsDataArr; Index: Integer): TabsDataArr;
var
NewSize: Integer;
i, Ind: Integer;
begin
NewSize := Length(TD) - 1;
if Index > NewSize {Length(TD) - 1} then raise Exception.Create('Указанный элемент не существует');

SetLength(Result, NewSize);
Ind := 0;

for i := 0 to High(TD) do
begin
if i <> Index then
begin
Result[Ind] := TD[i];
Inc(Ind);
end;
end;
end;
TD
Код:
procedure TFormPrivate.FormCreate(Sender: TObject);
begin
SetLength(TD, 0);
end;
Тогда заносить флаг для "мигания" в массив и при удалении и добвлении вкладок брать этот флаг из массива и далее производить нужные действия.
 
S

sinkopa

Первые косяки с внедрением кода.
...
Есть TabControl и его тень ввиде массива
Роман! Ну ёханый бабай!... Ну почему сразу нельзя внятно изложить ТЗ?
(1) Что ж Вы сразу не сказали, что у Вас есть контейнер для персональных Юзеря? Это же многое упрощает...
(2) Надрена, извиняюсь Вам массив (который тень TabControl-а)? В век ведь ООП жыж вроде живем... :D

Вот, держите:
Посмотреть вложение TabImageTimer3.rar
 
S

Shouldercannon

В каком формате сохранены иконки, которые вы вставили в ImageList? С вашими иконками всё норально, вставляю свои *.ico или *.bmp, так дёргаться начинают.
 
S

sinkopa

В каком формате сохранены иконки, которые вы вставили в ImageList? С вашими иконками всё норально, вставляю свои *.ico или *.bmp, так дёргаться начинают.
*.bmp, 16x16, 24bit, прозрачный цвет стандартный: RGB(255,0,255).
Если нужно, могу Ваши иконки сконвертить. Шлите мне на Email.
И еще... я тут подумал как можно уменьшить количество перерисовок контрола (соответственно и кол-во морганий/дёрганий)
вот что получилось (попробуйте, замените код "слушальщика" TTabControl.WMAlarmMSG):
Код:
procedure TTabControl.WMAlarmMSG(var Msg: TMessage);
var
i,ind: Integer;
TCItem: TTCItem; // добавить в uses CommCtrl
begin
if (Msg.Msg = WM_ALARM_MSG) and Visible then
begin

{Если не назначен Имажлист - выходим }
if (Self.Images = nil) then Exit;

FEvenAlarm := not FEvenAlarm;

{ Если пришла команда на запрет алармов
бежим по юзерам которые в закладках и выключаем Alarm
}
if (Msg.WParam = 0) then
begin
for i := 0 to Self.Tabs.Count-1 do
if (Self.TD[i] <> nil) then
Self.TD[i].Alarm := False;
end;

{ бежим по закладкам }
for i := 0 to Self.Tabs.Count-1 do
begin
{ получили текущий индекс картинки, для данного Таба }
TCItem.mask := TCIF_IMAGE;
SendMessage(Handle, TCM_GETITEM, i, Longint(@TCItem));

{ получили индекс картинки, который нужно назначить (новый) }
ind := GetImageIndex(i);

{ Если новый индекс отличается от текущего, то переназначаем }
if (TCItem.iImage <> ind) then
begin
TCItem.mask := TCIF_IMAGE;
TCItem.iImage := ind;
SendMessage(Handle, TCM_SETITEM, i, Longint(@TCItem));
end;
end;
end;
end;
 
S

Shouldercannon

Не получается адаптировать код для новой реализации работы с вкладками. Теперь из массива ничего не удаляется.
Проблема заключается в том, что после удаления вкладки, мигание иконки начинается на месте удалённой вкладки. Не получается побороть этот сдвиг
 

Вложения

  • pic.gif
    pic.gif
    51,4 КБ · Просмотры: 652
S

Shouldercannon

Успешно интегрировал код мигания в новый способ работы с вкладками в TabControl, но не могу проверить в действии код из link removed
Больше нет
Код:
 TabsDataArr = array of TTabsData;
...
var
...
TD: TabsDataArr;
Застрял здесь
Код:
if (Msg.WParam = 0) then
begin
for i := 0 to Self.Tabs.Count-1 do
if (Self.TD[i] <> nil) then
Self.TD[i].Alarm := False;
end;
не прокатывает
Код:
	if (Msg.WParam = 0) then
begin
for i := 0 to Self.Tabs.Count-1 do
if (TabUsers[i] <> nil) then
TabUsers[i].Alarm := False;
end;
 

Вложения

  • TabControl.zip
    31 КБ · Просмотры: 198
S

sinkopa

:D С какого извините "будуна" TabUsers[i] может вдруг оказаться nil если тип TTabUsers у Вас - record?
Код:
type
TTabUsers = record
UserID: Integer;
Nick: string;
TempMessage: string;
Alarm: Boolean;
end;

var
TabUsers: array of TTabUsers;

//...

{ Если пришла команда на запрет алармов
бежим по юзерам которые в закладках и выключаем Alarm
}
if (Msg.WParam = 0) then
begin
//!// Застрял тут
for i := 0 to Self.Tabs.Count-1 do
if (TabUsers[i] <> nil) then		// ????????!!!!!!!!!
TabUsers[i].Alarm := False;
end;
 
S

Shouldercannon

Бывает :D
Код:
	if (Msg.WParam = 0) then
begin
for i := 0 to Self.Tabs.Count-1 do TabUsers[i].Alarm := False;
end;
Надеюсь в дальнейшем не получу кирпич из-за того, что количество вкладок и количество записей в массиве разное.
Или лучше для страховки найти вкладку в массиве и там выставить
Код:
Alarm := False?
Нижнее подчёкивание вылезло
И при закрытии одной вкладки перестаёт мигать иконка у остальных вкладок :D Только у самой последней вкладки не перестаёт мигать
 

Вложения

  • Untitled_1.png
    Untitled_1.png
    23 КБ · Просмотры: 619
M

-master-

ужас, застрелить себя в ногу

Добавлено: нафик тут табы?
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!