Войти

Показать полную графическую версию : [решено] [C++] Как программно обновить содержимое окна


Drongo
22-03-2009, 21:31
Доброго здоровья всем. Собственно заинтересовался вопросом, возможно ли в С++ программно обновлять окно, не форму приложения. К примеру, выполняется программа, и нужно сделать так чтобы во время выхода она обновляла содержимое окна, папки. Как будто бы была дана команда ПКМ -> обновить или нажата клавиша F5. Как сделать, я не знаю совсем... :dont-know

Вопрос появился в связи с этой темой - Изменение в контекстном меню проводника (http://www.forum.oszone.net/thread-135445.html)

Admiral
23-03-2009, 00:09
Drongo, воспользуемся вариантом с эмуляцией клавиатурного нажатия F5.

Что б программно нажать и отпустить F5 нужен следующий код
keybd_event(VK_F5, 0, 0, 0);
keybd_event(VK_F5, 0, KEYEVENTF_KEYUP, 0);

Что б найти нужное окно, которое требуется обновить, воспользуемся Win32 API функцией FindWindow(), а что б сделать его активным - SetForegroundWindow()
Например, отправляем программное нажатие F5 в окно с заголовком "Мой компьютер"
#include <windows.h>
int main()
{
HWND SubjectWindow = FindWindowA(NULL,"Мой компьютер"); //Вместо NULL на первом параметре может быть явно указан класс окна,
//в случаи "Моего компьютера" это CabinetWClass. Поможет установить класс API функция GetClassName
SetForegroundWindow(SubjectWindow); //в паре с GetForegroundWindow которая указывает на активное окно

keybd_event(VK_F5, 0, 0, 0);
keybd_event(VK_F5, 0, KEYEVENTF_KEYUP, 0);

return 0;
}

Это не часть языка С\С++, а вызовы Windows API функций.

Drongo
23-03-2009, 10:34
Admiral, Класс!!! :up: То что нужно и работает отлично. :yes: Задача максимум решена.

А если такой вариант, окно открыто, программа отрабатывает и чтобы сразу после её выхода обновлялось бы активное окно, которое на момент выхода является активным\открытым? Возможно как-то домодернизировать предыдущий код?

Admiral
23-03-2009, 23:15
Нужно решить дилемму: что будет запускать функции нажатия и отпускания F5 если приложения нет в памяти?
Два варианта, выполняем выше код в виде отдельной проги запускаем батником или иным способом, когда основная закончила работу пускай мини приложение обновляет окно.
Насколько знаю по Делфи в среде от Борланда для формы есть события OnExit, OnDestroy быть может попробовать туда разместить?
На чистом АПИ данные события наступают когда приложению посылают сообщения WM_QUIT, WM_DESTROY, WM_CLOSE так что в этом случаи код пробовать нужно размещать в обработчик сообщений.

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

Drongo
24-03-2009, 11:21
Admiral, Я видимо не совсем правильно выражаюсь и путаю васи чтобы сразу после её выхода обновлялось бы активное окно »Не после, а в момент выхода, ну, чтобы это была последняя инструкция, которую выполняет программа перед выходом.
Я на форму кинул компонент Timer, в событии onTimer поставил такой код. Имеет он право на существование в таком виде? По сути, если его поставить перед Close();.

...
void __fastcall TForm1::tmr1Timer(TObject *Sender)
{
HWND SubjectWindow = FindWindowA(NULL, "Мой компьютер"); //Вместо NULL на первом параметре может быть явно указан класс окна,
//в случаи "Моего компьютера" это CabinetWClass. Поможет установить класс API функция GetClassName
SetForegroundWindow(SubjectWindow); //в паре с GetForegroundWindow которая указывает на активное окно

keybd_event(VK_F5, 0, 0, 0);
keybd_event(VK_F5, 0, KEYEVENTF_KEYUP, 0);

Close();
}
...

Admiral
27-03-2009, 21:07
Drongo ну почему же, это был бы оптимальным вариантом, если б окно обновлялось как раз именно после выгрузки программы из памяти, что б было в виде "пост инструкций". Кстати так происходит после выхода из 3d игр, но там это больше связанно с реакцией Эксплорера на переключение видеорежима.
А что касается в момент выхода, то там как раз те сложности про которые присущи второму варианту, если окно не скрыть то как раз своему же и отправится обновление, ибо функция keybd_event() не знает кому передавать, ибо нет соответственного параметра.
Что касается данного кода, то если он отрабатывает возложенные функции то имеет, только вот поиск и выделения окна не совсем то ибо требовалось обновлять активное, а это ведь совсем не обязательно окно "Моего Компьютера".

Drongo
28-03-2009, 20:30
Admiral, В первый коммент добавил ссылку на тему побудившую задать вопрос - Изменение в контекстном меню проводника (http://www.forum.oszone.net/thread-135445.html). Вы там ответили примером приведённым Котярой
Обновить можно ещё такой командой,

%SystemRoot%\System32\RUNDLL32.EXE user32.dll,UpdatePerUserSystemParameters >> (http://forum.oszone.net/post-986513.html#post986513)
, которую можно и в батник. »Но я не знаю как можно выполнить эту команду из программы, куда её вписать, и как?если окно не скрыть то как раз своему же и отправится обновление, ибо функция keybd_event() не знает кому передавать, ибо нет соответственного параметра. »Тоесть получается, что обновление будет для окна самой программы, правильно?Что касается данного кода, то если он отрабатывает возложенные функции то имеет, только вот поиск и выделения окна не совсем то ибо требовалось обновлять активное, а это ведь совсем не обязательно окно "Моего Компьютера". »Да, это может быть любое открытое окно. Другими словами это сделать невозможно?

P.S. Я просто не знаю, как это нужно сделать. Мог бы кто показать?

pva
28-03-2009, 22:31
http://www.codeproject.com/KB/shell/NSExtAddDelFld.aspx
вот это место:

BOOL CALLBACK RefreshShellView( HWND hWnd, LPARAM lParam )
{
if( hWnd )
{
TCHAR szClassName[MAX_PATH]=_T("");
DWORD dwLen=MAX_PATH;
GetClassName(hWnd,szClassName,dwLen);
if( (_tcscmp(szClassName,_T("ExploreWClass"))==0) ||
(_tcscmp(szClassName,_T("CabinetWClass"))==0) )
{
HWND hwndShellView =
FindWindowEx(hWnd,NULL,_T("NSFViewClass"),NULL);
if(hwndShellView !=NULL)
{
HWND hwndExcept =(HWND)lParam;
if((hwndExcept!=NULL && hwndExcept!=hwndShellView) ||
(hwndExcept==NULL))
::SendMessage(hwndShellView,WM_COMMAND,
ID_VIEW_REFRESH,0);
}
}
}
return( TRUE );
}

void RefreshShellViewWndsExcept(HWND hwndExcept)
{
// continue looping until done
for(; !EnumWindows((WNDENUMPROC) RefreshShellView,
(LPARAM) hwndExcept ); );
}

Admiral
31-03-2009, 01:47
Drongo можно вписать в первый параметр функции WinExec (http://msdn.microsoft.com/en-us/library/ms687393(VS.85).aspx) таким вот образомchar sysbuf[2*MAX_PATH];
GetSystemDirectoryA(sysbuf,MAX_PATH); //Получаем конкретный путь "%SystemRoot%\System32\" в виде C:\Windows, C:\WinXP, ...
strcat(sysbuf,"\\RUNDLL32.EXE user32.dll,UpdatePerUserSystemParameters 1,True"); //дописиваем команду с параметрами
WinExec(sysbuf,SW_HIDE); //приводим в исполнение, второй параметр в данном случаи по барабану, ибо данная команда и так не отображает никаких окон
Если не спрятать активную форму то да.
В общем, случаи после отработки программы не нужно выделять никаких окон, пуска программа просто пуляет F5, который попадёт в активное окно выделенное пользователём.




© OSzone.net 2001-2012