Re: AHK: AnimateWindow и StretchBlt
Не совсем понял, откуда мелькания. Я вчера набросал вариант со static со StretchBlt, никаких мельканий не заметил. Правда, с aero на другую тему переключаться не пробовал.
Вы не вошли. Пожалуйста, войдите или зарегистрируйтесь.
Чтобы отправить ответ, вы должны войти или зарегистрироваться
Не совсем понял, откуда мелькания. Я вчера набросал вариант со static со StretchBlt, никаких мельканий не заметил. Правда, с aero на другую тему переключаться не пробовал.
Ну тогда приведи свой код.
Ок, вечером.
#NoEnv
SetBatchLines, -1
Gui, +hwndhGui +AlwaysOnTop -DPIScale
Gui, Margin, 20, 20
Gui, Add, Pic, w351 h351 hwndhPic border
Gui, Show,, Zoom: 5
oZoom := new Zoom(hPic)
Return
GuiClose:
oZoom := ""
ExitApp
#If WinActive("ahk_id" . hGui)
WheelUp::
WheelDown:: Gui, Show,, % "Zoom: " . oZoom.ChangeZoom(A_ThisHotkey = "WheelUp")
#If
class Zoom {
__New(hPic) {
CoordMode, Mouse
this.hParent := DllCall("GetParent", Ptr, hPic)
WinGetPos,,, W, H, ahk_id %hPic%
this.PicWidth := W, this.PicHeight := H
this.CurrentZoom := 5
this.hDC := DllCall("GetDC", Ptr, hPic, Ptr)
this.hSDC := DllCall("GetDC", Ptr, 0, Ptr)
this.oMDC := new this.CompatibleDC(this.hDC, W, H)
this.hMDC := this.oMDC.hCDC
this.timer := timer := ObjBindMethod(this, "Draw")
SetTimer, % timer, 10
OnMessage( 0xF, ObjBindMethod(this, "WM_PAINT") )
}
__Delete() {
timer := this.timer
SetTimer, % timer, Delete
this.oMDC := ""
DllCall("DeleteDC", Ptr, this.hDC)
DllCall("DeleteDC", Ptr, this.hSDC)
}
Draw() {
MouseGetPos, mouse_x, mouse_y
w := this.PicWidth/this.CurrentZoom
h := this.PicHeight/this.CurrentZoom
DllCall("StretchBlt", Ptr, this.hDC, Int, 0, Int, 0, Int, this.PicWidth - 2, int, this.PicHeight - 2
, Ptr, this.hSDC, Int, mouse_x - w/2, Int, mouse_y - h/2, Int, w, Int, h, UInt, SRCCOPY := 0xCC0020)
this.BitBlt(this.hMDC, this.hDC)
}
BitBlt(ddc, sdc) {
DllCall("BitBlt", Ptr, ddc, Int, 0, Int, 0, Int, this.PicWidth, Int, this.PicHeight
, Ptr, sdc, Int, 0, Int, 0, UInt, SRCCOPY := 0xCC0020)
}
ChangeZoom(mode) {
this.CurrentZoom += (mode ? 1 : -1)
(this.CurrentZoom < 1 && this.CurrentZoom := 1)
Return this.CurrentZoom
}
WM_PAINT(wp, lp, msg, hwnd) {
if (this.hParent = hwnd) {
timer := ObjBindMethod(this, "BitBlt", this.hDC, this.hMDC)
SetTimer, % timer, -10
}
}
class CompatibleDC
{
__New(hDC, w, h) {
this.hCDC := DllCall("CreateCompatibleDC", Ptr, hDC, Ptr)
this.hCBM := DllCall("CreateCompatibleBitmap", Ptr, hDC, Int, w, Int, h, Ptr)
this.oBM := DllCall("SelectObject", Ptr, this.hCDC, Ptr, this.hCBM, Ptr)
}
__Delete() {
DllCall("SelectObject", Ptr, this.hCDC, Ptr, this.oBM, Ptr)
DllCall("DeleteDC", Ptr, this.hCDC)
DllCall("DeleteObject", Ptr, this.hCBM)
}
}
}
Всё равно немного заметен вертикальный рассинхрон и WM_PAINT в классической теме. И в моём случае this.hMDC это DC всего экрана, и WM_PAINT происходит медленне, плюс в цикле Draw уже неполучится каждый раз его сохранять.
Ещё не понятно, что у тебя показывается у краёв экрана.
Всё равно немного заметен вертикальный рассинхрон и WM_PAINT.
Это не понял.
И в моём случае this.hMDC это DC всего экрана
А зачем это? Для перерисовки картинки нужен только её контент.
Ещё не понятно, что у тебя показывается у краёв экрана.
Ну просто не учтена эта ситуация, думаю, вопрос на пару строк кода.
Это не понял.
Вертикальная синхронизация. Картинка разъежается по горизонтали, это в основном в классической теме, и не сильно заметно, но изредка режет глаз.
А зачем это? Для перерисовки картинки нужен только её контент.
Ну а если я захочу поставить на паузу, растянуть окно, и уменьшить зум, что я увижу?
Это не понял.
Про WM_PAINT я отвечал.
Ну а если я захочу поставить на паузу, растянуть окно, и уменьшить зум, что я увижу?
Думаю, это несколько избыточно, но решаемо. Просто сохранить последние координаты курсора, и при растягивании перерисовывать относительно этих координат по текущему размеру картинки.
Так экран уже поменяется 100 раз.
В моём варианте, если ты заметил, данные берутся непосредственно с DC экрана.
Так всё же что это даёт?
Прежде всего скорость. И всё время свежие данные.
Так это от задачи зависит, зачем свежие данные, если спустя время нужно будет просмотреть прежний вид всего экрана.
Так лучше иметь свежие, их всегда сохранить можно.
Чтобы отправить ответ, вы должны войти или зарегистрироваться