Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Программирование и базы данных (http://forum.oszone.net/forumdisplay.php?f=21)
-   -   [решено] [C++] Как программно обновить содержимое окна (http://forum.oszone.net/showthread.php?t=135502)

Drongo 22-03-2009 21:31 1071296

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

Вопрос появился в связи с этой темой - Изменение в контекстном меню проводника

Admiral 23-03-2009 00:09 1071430

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 1071760

Admiral, Класс!!! :up: То что нужно и работает отлично. :yes: Задача максимум решена.

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

Admiral 23-03-2009 23:15 1072644

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

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

Drongo 24-03-2009 11:21 1073028

Admiral, Я видимо не совсем правильно выражаюсь и путаю вас
Цитата:

Цитата Drongo
и чтобы сразу после её выхода обновлялось бы активное окно »

Не после, а в момент выхода, ну, чтобы это была последняя инструкция, которую выполняет программа перед выходом.
Я на форму кинул компонент 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 1076629

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

Drongo 28-03-2009 20:30 1077386

Admiral, В первый коммент добавил ссылку на тему побудившую задать вопрос - Изменение в контекстном меню проводника. Вы там ответили примером приведённым Котярой
Цитата:

Цитата Admiral
Обновить можно ещё такой командой,
Цитата:

Цитата Котяра
%SystemRoot%\System32\RUNDLL32.EXE user32.dll,UpdatePerUserSystemParameters >>

, которую можно и в батник. »

Но я не знаю как можно выполнить эту команду из программы, куда её вписать, и как?
Цитата:

Цитата Admiral
если окно не скрыть то как раз своему же и отправится обновление, ибо функция keybd_event() не знает кому передавать, ибо нет соответственного параметра. »

Тоесть получается, что обновление будет для окна самой программы, правильно?
Цитата:

Цитата Admiral
Что касается данного кода, то если он отрабатывает возложенные функции то имеет, только вот поиск и выделения окна не совсем то ибо требовалось обновлять активное, а это ведь совсем не обязательно окно "Моего Компьютера". »

Да, это может быть любое открытое окно. Другими словами это сделать невозможно?

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

pva 28-03-2009 22:31 1077522

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 1079652

Drongo можно вписать в первый параметр функции WinExec таким вот образом
Код:

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, который попадёт в активное окно выделенное пользователём.


Время: 04:48.

Время: 04:48.
© OSzone.net 2001-