Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Win Api
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 05.04.2013, 11:17   #1
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию Перетаскивание контрола по окну происходит не корректно

Здравствуйте.
В окне WinAPI имею контрол с классом "Static" (img: HWND). Изначально растянут под размер главного окна. Залит битмапом.
Нужно мышью перетаскивать этот img по главному окну.
Код:
type
tmypos = record
  Left : integer;
  Top : integer;
  Width : integer;
  Height : integer;
end;

procedure MyposToRect(const mypos:tmypos; var r: TRect);
begin
  SetRect(r,mypos.Left,mypos.Top,mypos.Left+mypos.Width,mypos.Top+mypos.Height);
end;


function ischildwnd(const w:HWND):Boolean;
var
  style : DWORD;
begin
  style := GetWindowLong(w,GWL_STYLE);
  Result := ((style and ws_child)=ws_child);
end;

procedure getwindowtpos(w:hwnd;var mypos:tmypos);
var
r: trect;
begin
  if ischildwnd(w) then
  begin
    getchildtpos(w,mypos);
    exit;
  end;
  getwindowrect(w,r);
  mypos.Left := r.Left;
  mypos.Top := r.Top;
  mypos.Width := r.Right - r.Left;
  mypos.Height := r.Bottom - r.Top;
end;

procedure getchildtpos(const child:hwnd;var mypos:tmypos);
var
r : trect;
owner : hwnd;
tp : TPoint;
begin
  owner := windows.getparent(child);
  GetWindowRect(child,r);
  tp.X := r.Left;
  tp.Y := r.Top;
  ScreenToClient(owner,tp);
  mypos.Left := tp.X;
  mypos.Top := tp.Y;
  mypos.Width := r.Right - r.Left;
  mypos.Height := r.Bottom - r.Top;
end;

procedure settext(w:hwnd; t:string);
begin
  if w>0 then
  sendmessage(w,wm_settext,0,lparam(pchar(t)));
end;

var
pos1 : tmypos;
bmp : tbitmap;

    WM_LBUTTONDOWN:
    if CanZoom then
    if bmp<>nil then
    begin
      OldX := loword(Lpar);
      OldY := HiWord(Lpar);
      Dragging := True;
    end;

    WM_LBUTTONUP:
    Dragging := False;

    WM_MBUTTONUP:
    begin
      CanZoom := not CanZoom;
      if CanZoom then
      begin
            checkmi(menu_ViewMode,id_normal_mode,True);
            checkmi(menu_ViewMode,id_tiled_mode,False);
            Resize(wnd);
        settext(wnd,'[ZOOM] '+cfg.PictureFile+ ' - '+mytitle1)
      end else
      begin
        Dragging := False;
      settext(wnd,cfg.PictureFile+ ' - '+mytitle1);
      end;
    end;

    WM_MOUSEMOVE:
    if Dragging then
    begin
      getwindowtpos(img,pos1);
      w := pos1.Width;
      h := pos1.Height;
      x := loword(Lpar);
      y := hiword(Lpar);
      x2 := pos1.Left+x-oldx;
      y2 := pos1.Top+y-oldy;
      settext(wnd,IntToStr(OldX)+','+inttostr(OldY)+';x='+IntToStr(X)+',y='+inttostr(Y)+';'+
                  IntToStr(pos1.Left)+','+inttostr(pos1.Top)+';x2='+
                  IntToStr(x2)+',y2='+inttostr(Y2)+',w='+IntToStr(w)+',h='+inttostr(h));
//      MoveWindow(img,x2,y2,w,h,True);

      ImageCanvas.StretchDraw(MyImageRect,bmp);
    end;
судя по цифрам, всё вроде сходится. Но, если раскомментировать MoveWindow, то окно перемещается странным образом. Если двинуть мышь и остановить, то окно продолжает двигаться.
не пойму, почему.

Последний раз редактировалось BLACK_RAIN; 05.04.2013 в 11:19.
BLACK_RAIN вне форума Ответить с цитированием
Старый 05.04.2013, 12:05   #2
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,330
По умолчанию

oldx/oldy надо обновлять после каждого сдвига в WM_MOUSEMOVE.
Кроме того, есть гораздо более простой способ - перехватить сообщение WM_NCHITTEST и вместо HTCLIENT возвращать HTCAPTION.
waleri вне форума Ответить с цитированием
Старый 05.04.2013, 12:46   #3
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию

Цитата:
Сообщение от waleri Посмотреть сообщение
oldx/oldy надо обновлять после каждого сдвига в WM_MOUSEMOVE.
Код:
      x := loword(Lpar);
      y := hiword(Lpar);
      oldx := ???;
      oldy := ???;
      x2 := pos1.Left+x-oldx;
      y2 := pos1.Top+y-oldy;
не соображу, на что их обновить?
Цитата:
Сообщение от waleri Посмотреть сообщение
Кроме того, есть гораздо более простой способ - перехватить сообщение WM_NCHITTEST и вместо HTCLIENT возвращать HTCAPTION.
Ага, про это слышал. Но тогда вроде не будет приходить WM_LBUTTONUP.
p.s. попробовал через WM_NCHITTEST. Возвращаю HTCAPTION. Но чего-то окно img не хочет двигаться. В другом проекте с Parent-окном это работает.
Подскажите лучше по первому варианту. На что менять oldx и oldy?

Последний раз редактировалось BLACK_RAIN; 05.04.2013 в 13:20.
BLACK_RAIN вне форума Ответить с цитированием
Старый 05.04.2013, 15:56   #4
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,330
По умолчанию

Сначала сдвинуть координаты, потом в oldx/oldy запомнить координаты мыши
waleri вне форума Ответить с цитированием
Старый 05.04.2013, 16:17   #5
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
Хорошо

Цитата:
Сообщение от waleri Посмотреть сообщение
Сначала сдвинуть координаты, потом в oldx/oldy запомнить координаты мыши
Спасибо! Заработало Просто шикарно
BLACK_RAIN вне форума Ответить с цитированием
Старый 08.04.2013, 11:30   #6
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию

А как сделать окно img пониз всех окон, чтобы остальные child-окна им не перекрывались? SetWindowPos(...,HWND_TOPMOST,...) не помогает.
Цитата:
Сообщение от MSDN
SetWindowPos function
Changes the size, position, and Z order of a child, pop-up, or top-level window. These windows are ordered according to their appearance on the screen. The topmost window receives the highest rank and is the first window in the Z order.


HWND_BOTTOM
(HWND)1

Places the window at the bottom of the Z order. If the hWnd parameter identifies a topmost window, the window loses its topmost status and is placed at the bottom of all other windows.
Однако
Код:
      SetWindowPos(img,HWND_BOTTOM,0,0,0,0,SWP_NOMOVE or SWP_NOSIZE);
тоже не помогает.

Последний раз редактировалось BLACK_RAIN; 08.04.2013 в 11:51.
BLACK_RAIN вне форума Ответить с цитированием
Старый 08.04.2013, 13:14   #7
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,330
По умолчанию

У child окон установлен флаг WS_CLIPSIBLINGS?
waleri вне форума Ответить с цитированием
Старый 08.04.2013, 13:27   #8
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию

Цитата:
Сообщение от waleri Посмотреть сообщение
У child окон установлен флаг WS_CLIPSIBLINGS?
нет. Сейчас поставил - не помогло. Что сделать?

Последний раз редактировалось BLACK_RAIN; 08.04.2013 в 15:09.
BLACK_RAIN вне форума Ответить с цитированием
Старый 09.04.2013, 07:29   #9
stabud
Пользователь
 
Регистрация: 28.03.2013
Сообщений: 14
По умолчанию

BLACK_RAIN! Покажи на скриншоте , что не получается и что требуется.
stabud вне форума Ответить с цитированием
Старый 09.04.2013, 09:22   #10
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию

Цитата:
Сообщение от stabud Посмотреть сообщение
BLACK_RAIN! Покажи на скриншоте , что не получается и что требуется.

при перетаскивании, окно img с фоткой перекрывает собой Statusbar и Progressbar, а надо, чтобы было наоборот.
BLACK_RAIN вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
как узнать ID контрола? BLACK_RAIN Win Api 2 03.05.2012 17:47
регистрация контрола Ципихович Эндрю Microsoft Office Word 0 04.04.2012 05:23
Привязка Контрола к контролу в массиве johnik1976 C# (си шарп) 2 21.02.2012 10:50
Текст из Edit контрола jungle Win Api 2 27.10.2009 19:22
Добавление контрола на форму ЯИмя Microsoft Office Excel 1 08.07.2009 15:58