Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Превью скринсейвера в Свойствах экрана

40K
25 сентября 2008 года
maxio
9 / / 18.09.2008
Доброго дня!

[ATTACH]3056[/ATTACH]

Пишу скринсейвер, столкнулся с этой проблемой - ну никак не удаётся что-то отрисовать в этом факин шит превью... :confused: В инете откопал следующую информацию: для отрисовки этого превью винда создаёт своё окошко, и передаёт в скринсейвер параметры "/p" (ну типа запуск в превью) и второй параметр типа "1313616" (я так понял, это хендл этого окошка или указатель на него - ну в этой области, в общем).

Если кто не знает, далее скринсейвер должен показывать превью так: никаких форм он не создаёт, и должен просто отрисовывать превью в это созданное виндой окошко. Я нашёл вроде полноценный исходник на делфи, но давно, видимо, торкал этот сибилдер, так как просто посмотреть в делфи и сделать тоже самое на билдере, я не смог :(

В общем, вот как выглядит кусок кода, обрабатывающий параметр /p у меня. Окна, хэндлы, их свойства, я не очень, к сожалению, шарю, поэтому буду рад, если кто поможет... Может быть, в этом коде даже написана откровенная чушь?.. не стесняйтесь, говорите )))

Код:
... Application->ShowMainForm = false
//это я ставлю при старте проекта, сразу после Application->Initialize
//а далее идёт текст из cpp файла к MainForm (форма одна)
...
if (UpperCase(ParamStr(1)) == "/P")
    {int n = ParamCount()+1;
      if (n > 2)
        {HWND parentInstance = HWND(StrToInt(ParamStr(2)));
          TCanvas *mCanvas = new TCanvas();
          mCanvas->Handle = GetDeviceContext(parentInstance);
          RECT parentRect;
          if (GetWindowRect(parentInstance, &parentRect))
            {mCanvas->Brush->Color = clRed;
              mCanvas->Brush->Style = bsDiagCross;
              try
               {if (IsWindowVisible(parentInstance))
                 {mCanvas->Rectangle(parentRect.left+1, parentRect.top+1, parentRect.right-1, parentRect.bottom-1);
                  }
                 }
              __finally
                 {mCanvas->Free();
                   Application->Terminate();
                  }
                }
        else {mCanvas->Free();
                Application->Terminate();
                }
          }
     Application->Terminate();
     }


Как я полагал вчера, когда пробовал запустить это всё - я должен увидеть в окне превью красный прямоугольник :D в лучшем случае ничо не видел - чёрное превью, а в худшем - возникал такой звук, как будто произошёл вылет, но без сообщений, экран оставался чёрным. Я делал лог-файл и писал туда всё по шагам. До момента IsWindowVisible лагов не было, а потом почему-то возникал этот звук, но приложение завершалось нормально и не зависало в памяти... Так же интересно: я писал в лог файл размеры окна прямоугольника, которые там получаю. И где бы окно свойств экрана не находилось - они всегда одни и те же, значения не менялись... (((

Помогите, пожалуйста, кто-нибудь разобраться!

Оригинальный исходник делфи, по которому я пытался проникнуть в суть вопроса, во вложенном архиве.
246
25 сентября 2008 года
GIZMO
1.8K / / 30.07.2004
Цитата: maxio

mCanvas->Free();


вот это точно херня полная, в С++ объекты удаляются так - delete mCanvas;

1
25 сентября 2008 года
kot_
7.3K / / 20.01.2000
во вторых - винда своего окошка НЕ создает. Это вы должны его создать и хендл эого окна передать канве. Ваш код - вобще фигня полная - например что все же вы получаете вторым параметром? И зачем читать его из параметров командной строки? Почему не сделать список доступных скринсейверов - с возможностью просмотреть каждый - вы же один хрен гуи-программу делаете - зачем же рвать гланды через непредназначенное для этого место?
Пример сброшу может седня вечером, если будет настроение и время - а если не будет - ищите сами - вариантов в нете - вагон и маленькая тележка.
40K
25 сентября 2008 года
maxio
9 / / 18.09.2008
Запинали несчастный мой код :D

Ну а вообще, может, мы недопоняли друг друга - я говорю и говорил про превью, которое должно показываться в том маленьком мониторчике на окне свойств:

[ATTACH]3055[/ATTACH]

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

Вторым параметром получает прога хендл какой-то. Проверял его IsWindow - возвращает true. И GetWindowRect возвращает в RECT постоянно одни и те же координаты...
1
26 сентября 2008 года
kot_
7.3K / / 20.01.2000
Если я вас правильно понял - то речь идет о том что вы хотите реализовать такое же поведение?
Попробуйте следующий код (к сожалению проверять его времени нет, так что тут разбирайтесь сами):
 
Код:
TStartupInfo siInfo;
TProcessInformation piInfo;
setmem(siInfo,sizeof(siInfo),0);
siInfo.cb = sizeof(siInfo);
siInfo.dwFlags = START_USESHOWWINDOW;
siInfo.wShowWindow = SW_SHOWNORMAL;
Sttring path = FileName+" -p "+IntToStr(Panel1->Handle);
CreateProcess(NULL,path.c_str(),NULL,NULL,false,0,NULL,NULL,&siInfo,piInfo);

естественно у вас на форме должна быть панель с таким именем, и FileName - это имя файла скринсейвера, которое вы получите каким либо удобным для вас образом. Я надеюсь приводить код как получить имя текущего хранителя экрана и список присуствующих в системе не нужно? Если нужно - то текущий храниетель экрана храниться в реестре - в ветке HKEY_CURRENT_USER\Control Panel\Desktop - параметр SCRNSAVE.EXE. Список присутствующих в системе вы получите, найдя все файлы с соотвествующим расширением.
1
26 сентября 2008 года
kot_
7.3K / / 20.01.2000
Да - если нужно просматривать скринсейверы из списка - объявите siInfo piInfo закрытыми переменными формы, siInfo проинициализируйте один раз в конструкторе, а перед CreateProcess вставъте следующий код:
 
Код:
if(piInfo.hProcess !=0)
 TerminateProcess(piInfo.hProcess,0);

и вместе с CreateProcess поместите в обработчик например клика по элементу списка.
40K
26 сентября 2008 года
maxio
9 / / 18.09.2008
kot_, большое спасибо за подсказки, и хотя мы правда не допоняли друг друга, ваш код мне дал хорошие наводки по поводу других идей, которые я буду реализовывать дальше!

Ну а вообще я пишу сам скринсейвер, одну прогу. Он и есть некий src Файл. И когда юзер выбирает его в этом списке в свойствах экрана - в маленьком мониторе должен отображаться он в уменьшенном размере. Но, как я выяснил, это не просто показать форму нужного размера.

Я нашёл, что при нажатии кнопки Просмотр, винда вызывает мой файл скринсейвера с параметром /s - это типа полноценный запуск, при нажатии кнопки "Параметры" - вызывает мой файл с параметром /c (так же там через двоеточие передаётся ещё какое-то целое число большое - полагаю, эт тоже какой-то хендл) - типа "/c:6122039". А чтобы показать мой скринсейвер в этом маленьком мониторе, когда пользователь его выбрал - передаются параметры: "/p 234902" - вот, это все исходные данные для нахождения где и как надо рисовать.

Я не знаю, как именно надо рисовать, но в инете нашёл (как в первом прикреплённом делфи-файле - там даже со страницей описания) - что надо рисовать с помощью канвы именно в этом маленьком мониторчике. Но как получить его координаты, я уже вообще не могу допереть ((((
246
26 сентября 2008 года
GIZMO
1.8K / / 30.07.2004
Цитата: maxio

А чтобы показать мой скринсейвер в этом маленьком мониторе, когда пользователь его выбрал - передаются параметры: "/p 234902" - вот, это все исходные данные для нахождения где и как надо рисовать.

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


Там же все ясно вроде, вот хендл тебе передают:

 
Код:
ParentSaverHandle := StrToInt(Param);

а потом рисуют на нем (окне):
Код:
procedure TMainForm.DoPreviewDrawing;
var
  Rect: TRect;
  Bitmap: TBitmap;
  Canvas: TCanvas;
begin
  FreeMutex; // Free the mutex so that the screen saver will actually run in preview
  Canvas := TCanvas.Create;
  try
    Canvas.Handle := GetDC(ParentSaverHandle);
    try
      GetWindowRect(ParentSaverHandle, Rect);
      // и т.д.
1
26 сентября 2008 года
kot_
7.3K / / 20.01.2000
в таком случае вобщек не понятно в чем ваша проблема.
Это не ваша задача - искать мониторчик :) вам ужет передают его хендл в параметре.
Исходник в делфи не смотрел - некогда.
Но возможно проблема в том что вы получаете дескритор и рисуете на канве - но после того как вы отрисовали - вам надо поместить нарисованное обратно в окно (типа CopyRect). Вы же канву удаляете - и с ней удаляется ваш рисунок. Может запутанно объяснил - но просто действительно времени особо нет.
14
26 сентября 2008 года
Phodopus
3.3K / / 19.06.2008
Цитата: maxio
...что надо рисовать с помощью канвы именно в этом маленьком мониторчике. Но как получить его координаты, я уже вообще не могу допереть ((((


А зачем тебе получать его координаты?! Только размер!
И Rect(0,0,Width,Height) - в нем и рисуй!

40K
26 сентября 2008 года
maxio
9 / / 18.09.2008
Хм... провёл пару экспериментов... как оказалось, вторым параметром передаётся хэндл, который принадлежит МОЕМУ окну. Поэтому и GetWindowRect возвращает всё время одни координаты (раньше они были похожи на размеры этого окна свойств экрана, что меня и запутало!)... Пробовал взять GetParent от этого своего окна - возвращает NULL

но как же тогда попасть в этот дурацкий мониторчик?! )))

>> Новый эксперимент!

Прописал тот же код не в коде основной формы, а в коде первого файла проекта, ещё до Application->Initialize(); ... Ну что могу сказать, я вообще не понимаю, что происходит, второй параметр один и тот же в двух лог-файлах, а вот GetWindowRect по нему возвращает разные значения! И вот до Application->Initialize(); получается именно нужный прямоугольник!.. Кто-то может предположить, как такое может быть и почему?!... 8\
14
26 сентября 2008 года
Phodopus
3.3K / / 19.06.2008
Как она не запустив твоей программы узнает хендл ею создаваемого окна??
40K
26 сентября 2008 года
maxio
9 / / 18.09.2008
В этой области я вообще не шарюсь, блин... ну у меня в билдере: один код прописан в главном cpp, где находится WinMain, внутри которого вызывается Application -> Initialize, Application->Run и так далее, и вот этот код, получив параметр через командную строку, находит по нему WindowRect равный нужному мониторчику. А вот если этот код выполняется в cpp файле создаваемой формы (по событию OnCreate) - по этому же параметру он выдаёт Rect, равный самой форме.

Может, приложение, создавая форму, просто замещает это спец. окно, и становится само доступно по этому хендлу?..

В общем, я пробовал это делать прямо по исходнику делфи, там до создания формы определяется только сам хэндл, а все операции с ним уже после FormCreate. Может быть, в этом плане билдер по-другому запускает-выполняет все эти формы-окны, фиг знает...

Да, если кто-то будет смотреть исходники от делфи, которые я приаттачил к первому сообщению - вот наводка, что там где:
ScreenSaveUtils - непосредственно код, обрабатывающий параметр ком. строки
randimg.dpr - основной код проекта, до запуска Application->Run
MainFrm.pas - код формы, которая прорисовывает превью и скринсейвер
в этой форме Create - инициализирует, чо выполнять
DoPreviewDrawing - осуществляет прорисовку скринсейвера в окошко превью
1
26 сентября 2008 года
kot_
7.3K / / 20.01.2000
Ві помоему сами запутались и других путаете. Зачем вам получать какие либо координаты? Причем тут "мониторчик"? Ваша задача - получить дескриптор того - куда рисовать - и туда рисовать. Все. Чего вы заморачиваетесь? Получения дескриптора "мониторчика" - не ваша задача, а того приложения которое этот "мониторчик" реализует.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог