WM_NCHITTEST: return HTCAPTION и PtInRegion()

Тема в разделе "WASM.WIN32", создана пользователем verelex, 16 апр 2008.

  1. verelex

    verelex New Member

    Публикаций:
    0
    Регистрация:
    15 ноя 2006
    Сообщения:
    90
    Xочу перетаскивать окно за любую точку, для этого:
    Код (Text):
    1.     case WM_NCHITTEST:
    2.         return HTCAPTION;
    3.         break;
    но перестает работать PtInRegion()
    Код (Text):
    1.     case WM_NCLBUTTONUP: // or WM_NCRBUTTONUP
    2.         xPos = GET_X_LPARAM(lParam);
    3.         yPos = GET_Y_LPARAM(lParam);
    4.         for (int i=0; i<iRegionsCount; i++)
    5.         {
    6.             if (PtInRegion(hRgns[i],xPos,yPos))
    7.             {
    8.                 iActiveRgn = i;
    9.                 continue;
    10.             }
    11.         }
    12.         break;
    Как поправить?
     
  2. piritus

    piritus Member

    Публикаций:
    0
    Регистрация:
    7 июл 2007
    Сообщения:
    36
    ; Двигать форму мышью за любую точку
    .if uMsg == WM_MOUSEMOVE
    mov eax,[wParam]
    cmp eax,1
    jne @@MF

    invoke ReleaseCapture
    invoke SendMessage,[hWin], WM_SYSCOMMAND, SC_MOVE+2, 0
    xor eax,eax

    @@MF:
    ret
     
  3. Sol_Ksacap

    Sol_Ksacap Миша

    Публикаций:
    0
    Регистрация:
    6 мар 2008
    Сообщения:
    623
    Как вариант:

    case WM_LBUTTONDOWN:
    DefWindowProc(hWnd, message, wParam, lParam);
    return DefWindowProc(hWnd, WM_NCLBUTTONDOWN, HTCAPTION, lParam);
     
  4. kero

    kero Модератор SOURCES & 2LZ Команда форума

    Публикаций:
    0
    Регистрация:
    4 апр 2006
    Сообщения:
    1.074
    Адрес:
    Москва
    Насчет драгдропа окна по uMsg==WM_MOUSEMOVE && wParam==MK_LBUTTON (piritus):

    для SendMessage(hWnd,WM_SYSCOMMAND,x,0) при x=SC_MOVE+2 либо x=SC_MOVE+1 добавка && wParam==MK_LBUTTON бесполезна.
    Но она необходима при x=SC_SIZE+9.

    verelex:
    Причем тут регионы ? Как понять "перестает работать PtInRegion" ? Пожалуйста, проясните, а то ваш код как-то до меня не доходит.
     
  5. piritus

    piritus Member

    Публикаций:
    0
    Регистрация:
    7 июл 2007
    Сообщения:
    36
    kero, да в данном случае это, возможно, не нужно...
    копировал из своего кода, там это необходимо, т.к. за @@MF идет заполнение структуры TRACKMOUSEEVENT и вызов TrackMouseEvent. Проверка, находится ли курсор над формой.
     
  6. kero

    kero Модератор SOURCES & 2LZ Команда форума

    Публикаций:
    0
    Регистрация:
    4 апр 2006
    Сообщения:
    1.074
    Адрес:
    Москва
    Короче, PtInRegion поминался тут всуе (а жаль).
    Суть же в том, что момент завершения драгдропа (отпускание мышки)
    ловится не по напрашивающемуся WM_NCLBUTTONUP,
    а - прдокс! - по WM_NCLBUTTONDOWN:
    Код (Text):
    1. .data
    2.  _ft    db "( %d , %d )  //  "
    3.  _class db "UpOrDown",0
    4. .data?
    5. .code
    6.  
    7. UpProc proc hWnd:HWND
    8.   local buf[128]:BYTE
    9.   local pt:POINT
    10.   invoke GetCursorPos,addr pt
    11.   invoke wsprintf,addr buf,offset _ft,pt.x,pt.y
    12.   invoke SetWindowText,hWnd,addr buf
    13.   ret
    14. UpProc endp
    15.  
    16. WndProc proc hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
    17.   .if uMsg==WM_DESTROY
    18.     invoke PostQuitMessage,0
    19.     xor eax,eax
    20.   .elseif uMsg==WM_NCHITTEST
    21.     mov eax,HTCAPTION
    22.   .else
    23.     invoke DefWindowProc,hWnd,uMsg,wParam,lParam
    24.     push eax
    25.     .if uMsg==WM_NCLBUTTONDOWN ; || uMsg==WM_NCLBUTTONUP, if WS_MAXIMIZE.
    26.       invoke UpProc,hWnd
    27.     .endif
    28.     pop eax
    29.   .endif
    30.   ret
    31. WndProc endp
     
  7. verelex

    verelex New Member

    Публикаций:
    0
    Регистрация:
    15 ноя 2006
    Сообщения:
    90
    Сорри, что долго не пояснял суть проблемы.
    Имеется фигура (Polygon):
    Код (Text):
    1. points->x=20; points->y=30;
    2. (points+1)->x=20; (points+1)->y=20;
    3. (points+2)->x=80; (points+2)->y=20;
    4. (points+3)->x=80; (points+3)->y=30;
    5. hRgns = CreatePolygonRgn(points,4,ALTERNATE);
    ...
    Код (Text):
    1. SetWorldTransform(...);// поворачиваем все на угол, напримкр 90 градусов
    2. //как я понял это привязывается к HDC.
    3. ...
    4. PaintRgn(hdc,hRgn);// повернут(перемещен) после SetWorldTransform()
    5. // все номально, он рисуется повернутым.
    ...
    далее, если мы сделаем перемещение формы(окна) за любую точку стандартным способом, то

    ничего не получится (у меня не получилось), т.к. при перемемещении курсора по горизонатли,

    фигура перемещается по другому (координатные оси смещены), поэтому использую WM_NC...
    Код (Text):
    1. case WM_NCRBUTTONUP:
    2.         point.x = GET_X_LPARAM(lParam);
    3.         point.y = GET_Y_LPARAM(lParam);
    4.         ScreenToClient(hWnd,&point);
    5.         //в WM_NCRBUTTONUP передаются screen-координаты, а в PtInRegion() - client.
    6.         for (int i=0; i<iRegionsCount; i++)
    7.         {
    8.             if (PtInRegion(hRgns[i],point.x,point.y))
    9.             {
    10.                 MessageBox(hWnd,"xe xe",NULL,MB_OK);
    11.                 continue;
    12.             }
    13.         }
    14.         break;
    //PtInRegion находит полигон в "прошлом" месте (в котором он был до вызова ф-ии

    SetWorldTransform). По-моему это из-за того, что не учитывается hdc.
    P.S. PtInRegion(hRgn,x,y) работает с координатами, в которых начало в верхем левом углу

    окна. И берет видимо points из RGNDATA (как и PaintRgn(hdc,hRgn)).
    Если бы была функция: PtInRegion(hdc,hrgn,x,y) ...
     
  8. kero

    kero Модератор SOURCES & 2LZ Команда форума

    Публикаций:
    0
    Регистрация:
    4 апр 2006
    Сообщения:
    1.074
    Адрес:
    Москва
    verelex
    >По-моему это из-за того, что не учитывается hdc.

    Боюсь, не из-за этого. Почему бы вам не все-таки не выложить здесь exe-иллюстрацию проблемы с полным исходником (чтобы исключить недосказанности вроде SetWorldTransform) ?
     
  9. kero

    kero Модератор SOURCES & 2LZ Команда форума

    Публикаций:
    0
    Регистрация:
    4 апр 2006
    Сообщения:
    1.074
    Адрес:
    Москва
    verelex
    Видимо, я все еще не ухватил суть вашей проблемы, потому как опять не удалось воспроизвести описанный вами феномен.
    Налицо и CreatePolygonRgn, и SetWorldTransform, и PaintRgn, - а окно перемещается вполне банально:
    Код (Text):
    1. R4toR4 macro v1,v2
    2.   fld  v1
    3.   fstp v2
    4. endm
    5.  
    6. XFORM4 struct
    7.   eM11  REAL4 ?
    8.   eM12  REAL4 ?
    9.   eM21  REAL4 ?
    10.   eM22  REAL4 ?
    11.   ex    REAL4 ?
    12.   ey    REAL4 ?
    13. XFORM4 ends
    14.  
    15. .data
    16.  _class db "test",0
    17.  pts    dd 100,40, 100,10, 180,10, 180,40
    18.  cos_   REAL4  0.8660 ; (angle=30°)
    19.  sin_   REAL4  0.5000
    20.  nsin_  REAL4 -0.5000
    21.  xy_    REAL4  0.0
    22. .data?
    23.  hrgn   HRGN ?
    24.  flag   dd ?
    25. .code
    26.  
    27. WndProc proc hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
    28.   local ps:PAINTSTRUCT
    29.   local hdc:HDC
    30.   local xform4:XFORM4
    31.  
    32.   .if uMsg==WM_DESTROY
    33.     invoke DeleteObject,hrgn    
    34.     invoke PostQuitMessage,0
    35.     xor eax,eax
    36.   .elseif uMsg==WM_CREATE    
    37.     invoke CreatePolygonRgn,addr pts,4,ALTERNATE
    38.     mov hrgn,eax
    39.     xor eax,eax
    40.   .elseif uMsg==WM_PAINT
    41.     invoke BeginPaint,hWnd,addr ps
    42.     mov hdc,eax    
    43.     invoke SetGraphicsMode,hdc,GM_ADVANCED
    44.     R4toR4  cos_, xform4.eM11
    45.     R4toR4  sin_, xform4.eM12
    46.     R4toR4 nsin_, xform4.eM21
    47.     R4toR4  cos_, xform4.eM22
    48.     R4toR4  xy_ , xform4.ex  
    49.     R4toR4  xy_ , xform4.ey
    50.     invoke SetWorldTransform,hdc,addr xform4
    51.     invoke PaintRgn,hdc,hrgn
    52.     invoke ModifyWorldTransform,hdc,addr xform4,MWT_IDENTITY
    53.     invoke SetGraphicsMode,hdc,GM_COMPATIBLE
    54.     invoke EndPaint,hWnd,addr ps
    55.     xor eax,eax
    56.   .elseif uMsg==WM_NCHITTEST && flag==0
    57.     mov eax,HTCAPTION
    58.   .elseif uMsg==WM_MBUTTONDOWN || uMsg==WM_NCMBUTTONDOWN
    59.     xor flag,1
    60.     xor eax,eax
    61.   .else
    62.     invoke DefWindowProc,hWnd,uMsg,wParam,lParam
    63.   .endif
    64.   ret
    65. WndProc endp
     
  10. verelex

    verelex New Member

    Публикаций:
    0
    Регистрация:
    15 ноя 2006
    Сообщения:
    90
    Спасибо.
     
  11. kero

    kero Модератор SOURCES & 2LZ Команда форума

    Публикаций:
    0
    Регистрация:
    4 апр 2006
    Сообщения:
    1.074
    Адрес:
    Москва
    verelex
    >Спасибо.

    1) Ну, и зачем вы стерли пост, который наконец-то объяснял, что вам надо? Теперь придется его цитировать...
    2) Прилагаю прикидочный черновичок для регионов (которым, кстати, SetworldTransform без надобности):
    Код (Text):
    1. XFORM4 struct
    2.   eM11  REAL4 ?
    3.   eM12  REAL4 ?
    4.   eM21  REAL4 ?
    5.   eM22  REAL4 ?
    6.   ex    REAL4 ?
    7.   ey    REAL4 ?
    8. XFORM4 ends
    9.  
    10. .data
    11.   _class db "XFORM_4_REGION",0
    12.   plgn   dd 100,80, 100,50, 180,50, 180,80, 140,100 ; (polygon, 5 points)
    13.   angle  dd 45 ; (45°)
    14.  
    15. .data?
    16.   hrgn   HRGN ?
    17.   x0     dd ?
    18.   y0     dd ?
    19.   drdr   dd ? ; (region dragdrop)
    20.   htflag dd ? ; (window dragdrop)
    21.  
    22. .code
    23.  
    24. XformRotation proc angl:DWORD,x:DWORD,y:DWORD,lpxform:DWORD
    25.   local val:DWORD
    26.   mov ecx,lpxform
    27.   assume ecx:ptr XFORM4
    28.   mov val,180
    29.   fldpi
    30.   fimul angl
    31.   fidiv val
    32.   fsincos
    33.   fst  [ecx].eM11 ; (cos)
    34.   fstp [ecx].eM22 ; (cos)
    35.   fst  [ecx].eM12 ; (sin)
    36.   fchs
    37.   fstp [ecx].eM21 ; (-sin)
    38.   fild x
    39.   fstp [ecx].ex
    40.   fild y
    41.   fstp [ecx].ey
    42.   assume ecx:nothing
    43.   ret
    44. XformRotation endp
    45.  
    46. XformRotationRgn proc uses ebx edi rgn:HRGN,angl:DWORD,lpxform:DWORD
    47.   invoke GetRegionData,rgn,0,0
    48.   mov ebx,eax ; (dwCount)
    49.   invoke VirtualAlloc,0,ebx,MEM_COMMIT,PAGE_READWRITE
    50.   mov edi,eax ; (lpRgnData)
    51.   invoke GetRegionData,rgn,ebx,edi
    52.   invoke XformRotation,angl,0,0,lpxform  
    53.   invoke ExtCreateRegion,lpxform,ebx,edi
    54.   push eax
    55.   invoke VirtualFree,edi,0,MEM_RELEASE  
    56.   invoke DeleteObject,rgn ; (old hrgn)
    57.   pop eax ; (new hrgn)
    58.   ret
    59. XformRotationRgn endp
    60.  
    61. ClientPtInRgn proc uses ebx hWnd:HWND,rgn:HRGN,lppt:DWORD
    62.   mov ebx, lppt
    63.   assume ebx:ptr POINT
    64.   invoke GetCursorPos,ebx
    65.   invoke ScreenToClient,hWnd,ebx
    66.   invoke PtInRegion,rgn,[ebx].x,[ebx].y
    67.   assume ebx:nothing
    68.   ret
    69. ClientPtInRgn endp
    70.  
    71. WndProc proc uses ebx edi hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
    72.   local pt:POINT
    73.   local rt:RECT
    74.   local ps:PAINTSTRUCT  
    75.   local xform:XFORM4
    76.  
    77.   .if uMsg==WM_DESTROY
    78.     invoke DeleteObject,hrgn
    79.     invoke PostQuitMessage,0
    80.     xor eax,eax
    81.  
    82.   .elseif uMsg==WM_CREATE
    83.     invoke CreatePolygonRgn,addr plgn,4,ALTERNATE
    84.     mov hrgn,eax
    85.     mov eax,80000001h
    86.     jmp @f
    87.  
    88.   .elseif uMsg==WM_MOUSEWHEEL
    89.     mov eax,wParam
    90. @@:
    91.      mov ecx,angle
    92.     .if eax<80000000h
    93.       neg ecx
    94.     .endif    
    95.     invoke XformRotationRgn,hrgn,ecx,addr xform
    96.     mov hrgn,eax
    97.     invoke InvalidateRect,hWnd,0,1
    98.     xor eax,eax
    99.  
    100.   .elseif uMsg==WM_PAINT
    101.     invoke BeginPaint,hWnd,addr ps
    102.     invoke PaintRgn,eax,hrgn
    103.     invoke EndPaint,hWnd,addr ps
    104.     xor eax,eax
    105.  
    106.   .elseif uMsg==WM_LBUTTONDOWN && drdr==0
    107.     invoke ClientPtInRgn,hWnd,hrgn,addr pt
    108.     .if eax!=0
    109.       mov drdr,eax
    110.       mov eax,pt.x
    111.       mov x0,eax
    112.       mov eax,pt.y
    113.       mov y0,eax
    114.     .endif
    115.     jmp @dwp
    116.  
    117.   .elseif uMsg==WM_LBUTTONUP && drdr!=0
    118.     xor eax,eax
    119.     mov drdr,eax
    120.     jmp @dwp
    121.  
    122.   .elseif uMsg==WM_MOUSEMOVE && wParam==MK_LBUTTON
    123.     invoke ClientPtInRgn,hWnd,hrgn,addr pt
    124.     .if drdr!=0
    125.       .if eax!=0
    126.         mov eax,pt.x
    127.         mov edx,x0
    128.         mov x0,eax
    129.         sub eax,edx
    130.         mov ecx,pt.y
    131.         mov edx,y0
    132.         mov y0,ecx
    133.         sub ecx,edx
    134.         invoke OffsetRgn,hrgn,eax,ecx
    135.         invoke InvalidateRect,hWnd,0,1
    136.       .else
    137.         mov drdr,eax
    138.       .endif
    139.     .else
    140.       jmp @dwp
    141.     .endif
    142.  
    143.   .elseif uMsg==WM_MBUTTONDOWN || uMsg==WM_NCMBUTTONDOWN
    144.     xor htflag,1
    145.     xor eax,eax
    146.  
    147.   .elseif uMsg==WM_NCHITTEST && htflag!=0
    148.     invoke ClientPtInRgn,hWnd,hrgn,addr pt  
    149.     .if eax==0
    150.       mov eax,HTCAPTION
    151.     .else
    152.       jmp @dwp    
    153.     .endif
    154.  
    155.   .else
    156. @dwp:
    157.     invoke DefWindowProc,hWnd,uMsg,wParam,lParam
    158.   .endif
    159.   ret
    160. WndProc endp
    Включить/выключить драгдроп окна: клик средней кнопки мышки (попутно меняется и курсор: с лапы на стрелку).
    Драгдроп и окна, и региона - как обычно: левой кнопкой.

    Повернуть регион (а точнее - заменить старый новым, повернутым): мышкино колесико вперед/назад => поворот на угол +45°/-45°.
    Покрутите колесико туда-сюда подольше...
     
  12. kero

    kero Модератор SOURCES & 2LZ Команда форума

    Публикаций:
    0
    Регистрация:
    4 апр 2006
    Сообщения:
    1.074
    Адрес:
    Москва
    >Спасибо.
    Пожалуйста.