Сейчас на форуме: vasilevradislav, tyns777, zombi-vadim (+3 невидимых)

 eXeL@B —› Программирование —› Как побороть отрисовку?
Посл.ответ Сообщение

Ранг: 72.7 (постоянный)
Активность: 0.080
Статус: Участник

Создано: 17 февраля 2008 23:12 · Поправил: Small_S
· Личное сообщение · #1

Привет всем! Сразу прошу прощения модераторов, что сабж не вполне по реверсу или кодингу по реверсу,
но как знать может при оформлении и реверс-прог кому то пригодится знание этого. Кроме того, для меня
это имеет прямое отношение к занятиям изучения защит,- я просто пытаюсь освободить своё время путем
автоматизации различной отчётности на работе

Итак суть проблемы: Создал прогу которая сама открывает протоколы одного из моих приборов и читает
измерения шести характеристик в таблицу(StringGrid1),а список открытых протоколов,-точнее имена их файлов пишутся в CheckListBox1, после чего смотрит два параллельных измерения в одних условиях
по всем шести компонентам и если расхождение хоть по одному из них превышает допустимый предел, то
подсвечивает красным компонент за первым из данной параллели(тоесть всегда сверяет с предыдущим) и
в колонке заключения пишет не удовлетворительно. Для экономии места оба элемента(StringGrid1 и CheckListBox1) находятся на первой вкладке(TabSheet1) компонента PageControl1.Да и ещё, чекбоксы над таблицей позволяют отключить проверку любой из шести характеристик(тогда даже при неуде подсвечивание с клеток принадлежащих этой характеристике исчезает). Чекбоксы CheckListBox1 позволяют убрать из расчёта любой(ые) протокол(ы)и список подтягивается кверху. Кроме того протоколы фильтруются по трём различным условиям и на ещё одном нижнем чекбоксе. Всё было зашибись пока при разработке не появилась необходимость подсвечивать красным. При автоматической перерисовке StringGrid1-да(она стоит по умолчанию) удалось подсвечивать только по исключению характеристик при нажатиях верхних чекбоксов, отвечающих за их отключение. Пришлось выставить DefaultDrawing
в False и написать собственную отрисовку по событию OnDrawCell тоже самое пришлось сделать и с CheckListBox1 ибо при переключениях страниц PageControl1-ла список открытых протоколов "исчезал"(становился невидим).

Что то скрин не закачался, кому интересно смотрим в аттаче опенофисовский рисунок скрина.
Наконец ссыль на скрин проги: _http://rapidshare.com/files/92807748/__1089___1082___1088___1080___10 85_.zip.html
тут только картинка проги, с уже обработанным каталогом, понятно, что по кнопке "Выбор каталога" должен всегда лезть этот выбор

Теперь всё работает нормально,но при попытке выбрать другой каталог во второй раз окно диалога отображается под TabSheet1 и нужно переключиться на TabSheet2 тогда его видно и вернуться на TabSheet1(тогда оно не пропадает) Самое интересное, что по началу я надавил на кнопку "Выбор каталога" раза 3-4 и на раз 4-й диалоговое окно всё же вылазит на "поверхность"(становится над TabSheet1). Но во первых к тому моменту между TabSheet1 и TabSheet2 уже их штуки 3 открыто, во вторых это гон, надо чтобы как и раньше окно выпрыгивало только клацнеш на кнопке "Выбор каталога". Я понимаю, что виновата отрисовка StringGrid1 и CheckListBox1(после неё началась дребедень), но без ручной отрисовки никак.Погуглил вчера на эту тему- поднятия окна над всеми. Нашёл только рекомендации:

а) использовать функцию SetWindowPos(должна выводить окно над всеми вообще)

SetWindowPos(Handle,HWND_TOPMOST,Left,Top,Width,Height,SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE);
чё то не берёт(может неправильно использую или она не действует на дочерние окна?)

б) использовать функцию SetForegroundWindow(должна отдавать фокус окну)

SetForegroundWindow(Handle), что то тоже не действует.
Ну теперь уже понятно почему не берёт,- потому как хэндл этого диалогового окна не удаётся взять.

Пытаюсь так:

procedure TForm2.Button3Click(Sender: TObject);
var
TitleName : string;
lpItemID : PItemIDList;
BrowseInfo : TBrowseInfo;
DisplayName : array[0..MAX_PATH] of char;
TempPath : array[0..MAX_PATH] of char;
Hadler: THandle;//НЕ ВОЗМУЩАТЬСЯ Я ЛЮБЛЮ ПОКОВЕРКАТЬ ЛЮБЫЕ СЛОВА, ОСОБЕННО ИНГЛИШ
classname: PChar;
classname1: integer;
begin
FillChar(BrowseInfo, sizeof(TBrowseInfo), #0);

{with BrowseInfo do
SetWindowPos(Handle,HWND_NOTOPMOST,Left,Top,Width,Height,SWP_NOACTIVAT E or SWP_NOMOVE or SWP_NOSIZE);
SetForegroundWindow(Handle); }
//ЭТО ПО НАЧАЛУ ПЫТАЛСЯ БРАТЬ УКАЗАТЕЛЬ НА ЭТО ЧУДО-ЮДО-BrowseInfo И ИСПОЛЬЗОВАТЬ

BrowseInfo.hwndOwner := Form1.Handle;
BrowseInfo.pszDisplayName := @DisplayName;
TitleName := 'Please specify a directory';
BrowseInfo.lpszTitle := PChar(TitleName);
BrowseInfo.ulFlags := BIF_RETURNONLYFSDIRS;
lpItemID := SHBrowseForFolder(BrowseInfo);

if lpItemId <> nil then
begin //ТУТ УКАЗАТЕЛЬ НА РОДИТЕЛЯ С ГОРЯ((((
classname1:= GetClassName(BrowseInfo.hwndOwner,classname,128);//И ЧТО ТОЛЬКО НЕ ПЫТАЛСЯ БРАТЬ
Hadler:= FindWindowA(classname,'Please specify a directory'); // ЗА ХЭНДЛ ЭТОГО ОКНА ДИАЛОГА НОЛЬ И
SetForegroundWindow(Hadler); //ВСЁ ТУТ, ХОТЬ ТРЕСНИ(((((((
SHGetPathFromIDList(lpItemID, TempPath);

new_My_dir:= TempPath;// новый рабочий каталог будет таким
if My_dir <> new_My_dir then
begin
CheckListBox1.Clear; //чистим после предыдущего списка
My_dir:= new_My_dir+''; //присваиваем новое значение директории
ListFileDir(My_dir,CheckListBox1.Items);
vibor_new_My_dir:=1; //выставляем флаг что мы не в первый раз
OnPaint(Sender);
end;

GlobalFreePtr(lpItemID);
end else

Global(Sender); //этот вызов против глюка когда вызываем окно выбора каталога и оно при закрытии без
end; //выбора стирает список файлов протоколов

Так вот и вопрос, уважаемые знатоки, как говорят, в одной широко известной передаче : как можно эту заразу -SHBrowseForFolder(BrowseInfo) приподнять над отрисовывающимися (StringGrid1 и CheckListBox1)???
Уже все мозги высушил над этим головняком?



Ранг: 54.0 (постоянный)
Активность: 0.020
Статус: Участник

Создано: 18 февраля 2008 07:26 · Поправил: Pro100ya
· Личное сообщение · #2

На момент if lpItemId <> nil then окно уже закрыто, искать нечего. Попробуй вывести выбор папки в отдельную процедуру. Еще в качестве BrowseInfo.hwndOwner можно попробовать PageControl1



Ранг: 72.7 (постоянный)
Активность: 0.080
Статус: Участник

Создано: 18 февраля 2008 11:27
· Личное сообщение · #3

Pro100ya Буду пробовать, как приду домой, в отдельную процедуру, ну и попробую загнать как родителя PageControl1, хотя может уже пробовал, ну ещё эти три строки в который раз покидаю в разных местах. Так вчера запостил, потому что уже, где только их не вставлял, и выше, и ниже.

Можно ещё, кто знает, выложить здесь любой другой способ задания диалога выбора рабочей директории без использования SHBrowseForFolder(BrowseInfo), желательно чтобы ломилось окно диалога наверх несмотря ни на какие отрисовки.



Ранг: 54.0 (постоянный)
Активность: 0.020
Статус: Участник

Создано: 18 февраля 2008 11:57
· Личное сообщение · #4

Можно повесить FindWindow/SetForegroundWindow на таймер, включить его, потом SHBrowseForFolder, выключить. Раз уж такой затык



Ранг: 72.7 (постоянный)
Активность: 0.080
Статус: Участник

Создано: 18 февраля 2008 21:51
· Личное сообщение · #5

Хочу прежде всего поблагодарить Pro100ya за предлагаемые решения, хотя они и не помогли. А далее. Сорри перед всеми, от я тупанул. Ларец открывался просто до безобразия.
Надо всего лишь ввести внутримодульную переменную любую с двумя состояниями и в самом начале процедуры формирования диалога её включать, а в самом конце выключать. А в самом начале процедуры прорисовки проверять вкл или выкл и если вкл, то не давать рисовать. Например:

в голове модуля
var
nov_vib_dir: byte;
.....................................
.....................................
procedure TForm2.Button3Click(Sender: TObject);
var
TitleName : string;
lpItemID : PItemIDList;
BrowseInfo : TBrowseInfo;
DisplayName : array[0..MAX_PATH] of char;
TempPath : array[0..MAX_PATH] of char;
Hadler: THandle;
classname: PChar;
classname1: integer;

begin
___nov_vib_dir:= 1;
___FillChar(BrowseInfo, sizeof(TBrowseInfo), #0);
...................................................................... ...
...................................................................... ...
___ Global(Sender);
___ nov_vib_dir:= 0;
end;

И если в OnDrawCell - nov_vib_dir ни дай бог не ноль, то хрен StringGrid1-ду, а не отрисовка.
Единственно ещё прийдётся заделать процедуру на предмет тащим ли драп- дропом окно диалога или нет, а то в том виде как сейчас им можно как резинкой в StringGrid1 затирать данные.

И ещё пару приколов, когда рисовало когда хотело, время от времени на крайних кнопках появлялись артефакты, а то и вообще они становились прозрачными(аж лужайку по которой дядя билли любит гулять видно). После этой заморозки во время диалога, всякое артефактирование кнопок прекратилось, причем и не вовремя заморозки. Сама перерисовка перестала мерцать(ранее такое иногда было заметно). Просто чудо какое-то, трёх зайцев триплетом.

Вот только я так и не понял причём здесь кнопки и перерисовка StringGrid1-да. Что их роднит, если кнопки на Form2, а StringGrid1 на PageControl1, который в свою очередь на Form2. Самый ближайший общий родственник это дедушка Form2. Причём судя по полному отсутствию артефактов и, причём всегда, botton2(средняя кнопка) в этой семейке,- вольная птица, действующая по принципу,- пусть всё вокруг горит хоть синим пламенем, а я нормальная кнопка. Весьма забавно ведут себя три из шести верхних чекбоксов. Они не мерцают зато их было видно и они даже работали на обоих TabSheet-ах PageControl1-ла одновременно, пока я специально не прописал их в невидимость при переключениях TabSheet-ов.

Что же касается преложенных Pro100ya мер по назначению BrowseInfo нового родителя, то там хоть папу римского назнач ему в хозяина, ему фиолетово. Все равно перерисовка сверху. FindWindowA видит почемуто только класс и заголовочную строку формы первой или второй, а данное диалоговое окно остаётся невидимым для неё.

Пока закрывать тему не буду, вдруг кто то знает способ отобразить окно диалога поверх любой отрисовки , интересно же, возможно такое или нет?


 eXeL@B —› Программирование —› Как побороть отрисовку?
:: Ваш ответ
Жирный  Курсив  Подчеркнутый  Перечеркнутый  {mpf5}  Код  Вставить ссылку 
:s1: :s2: :s3: :s4: :s5: :s6: :s7: :s8: :s9: :s10: :s11: :s12: :s13: :s14: :s15: :s16:


Максимальный размер аттача: 500KB.
Ваш логин: german1505 » Выход » ЛС
   Для печати Для печати