CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - Lepkie formularze

Lepkie formularze

dział ogólny

Re: Lepkie formularze

Nowy postprzez Cyfrowy Baron » piątek, 31 maja 2013, 19:07

No nie wiem... System zawsze przyciąga okno do kursora póki przycisk myszy nie zostanie zwolniony.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Lepkie formularze

Nowy postprzez polymorphism » piątek, 31 maja 2013, 19:53

Jak zrobi własną obsługę, to system nic nie będzie przyciągał. W WM_NCLBUTTONDOWN możesz zablokować jakąkolwiek reakcję na klika myszy w pasku tytułowym, a co za tym idzie systemowe przeciąganie okna.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Lepkie formularze

Nowy postprzez Cyfrowy Baron » sobota, 1 czerwca 2013, 09:04

Problem w tym, że w trakcie przesuwania masz pewien zakres na który okno reaguje. Margines wynosi np. 30 pikseli, czyli gdy okno wchodzi w margines to zaczyna się przyciąganie, ale wciąż trzymam okno i niewielki ruch myszą znów wywołuje kod przyciągający, dopóki nie zwolnię klawisza myszy. Zastanawiam się raczej na funkcją dokowania, która jest dostępna dla okien, bo Twój pomysł raczej się nie sprawdzi. Problem z dokowaniem polega na tym, że nigdy tego nie robiłem i musiałbym się z tym dopiero zapoznać, a mi przecież nie jest to potrzebne...
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Lepkie formularze

Nowy postprzez polymorphism » sobota, 1 czerwca 2013, 09:28

Cały czas nie rozumiem, o co Tobie chodzi, gdzie tu widzisz problem. Przecież jeśli napisze własną metodę przeciągania okna, od zera, to będzie miał pełną kontrolę nad tym, jak to okno będzie reagować po przyciągnięciu do krawędzi. Nie wydaje mi się to nawet jakieś trudne w realizacji...
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Lepkie formularze

Nowy postprzez polymorphism » sobota, 1 czerwca 2013, 15:27

Z racji tego, że dawno nie nic kodziłem, zapodam przykładowy kod, realizujący to, o czym pisałem wyżej:
KOD cpp:     UKRYJ  
WNDPROC oldWindowProc = NULL;
int     xWndOffset;
int     yWndOffset;
bool    isDragging = false;
int     snapThreshold = 30;

void moveSnapWindow(HWND hwnd, int x, int y)
{
        RECT rc;

        GetWindowRect(hwnd, &rc);

        int scr_w = GetSystemMetrics(SM_CXSCREEN);
        int scr_h = GetSystemMetrics(SM_CYSCREEN);

        if(abs(x) < snapThreshold) x = 0;
        if(abs(y) < snapThreshold) y = 0;
        if(abs(scr_w - (x + rc.right - rc.left)) < snapThreshold) x = scr_w - (rc.right - rc.left);
        if(abs(scr_h - (y + rc.bottom - rc.top)) < snapThreshold) y = scr_h - (rc.bottom - rc.top);

        MoveWindow(hwnd, x, y, rc.right - rc.left, rc.bottom - rc.top, TRUE);
}

LRESULT CALLBACK newWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
        if(msg == WM_NCLBUTTONDOWN && wParam == HTCAPTION)
        {
                RECT rc;

                GetWindowRect(hwnd, &rc);

                xWndOffset = GET_X_LPARAM(lParam) - rc.left;
                yWndOffset = GET_Y_LPARAM(lParam) - rc.top;

                SetCapture(hwnd);
                isDragging = true;
                return 0;
        }


        if(isDragging && msg == WM_MOUSEMOVE)
        {
                POINT pt = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
                ClientToScreen(hwnd, &pt);
                moveSnapWindow(hwnd, pt.x - xWndOffset, pt.y - yWndOffset);
                return 0;
        }

        if(isDragging && msg == WM_LBUTTONUP)
        {
                isDragging = false;
                if(hwnd == GetCapture())
                        ReleaseCapture();
               
                POINT pt = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
                ClientToScreen(hwnd, &pt);
                moveSnapWindow(hwnd, pt.x - xWndOffset, pt.y - yWndOffset);
                return 0;
        }

        if(isDragging && msg == WM_CAPTURECHANGED)
        {
                isDragging = false;
        }

        return CallWindowProc(oldWindowProc, hwnd, msg, wParam, lParam);
}

W przykładzie okno subklasowałem (oldWindowProc -> newWindowProc), ale jeśli jest dostęp do procedury obsługi, to podmiana jej wydaje się zbędna, wystarczy dodać obsługę komunikatów - powinno działać.

moveSnapWindow przesuwa okno na podaną pozycję z dociągnięciem do boków ekranu. Wystarczy dostosować sobie tę funkcję do własnych potrzeb.

Oczywiście kod mogłem zrobić bardziej obiektowo i uniwersalnie, ale... to już wasza działka ;)
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Lepkie formularze

Nowy postprzez Cyfrowy Baron » sobota, 1 czerwca 2013, 18:03

No i nic się nie zmieniło, okno skacze jak skakało no i przyciąga do brzegu ekranu, a żeby tak zrobić nie potrzeba żadnego kodu, bo formularz ma już potrzebną funkcję... ale już się przyzwyczaiłem, że nie sprawdzasz swoich kodów. No, ale mnie ten kod nie potrzebny, więc nie będę się nad tym rozwodził.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Lepkie formularze

Nowy postprzez polymorphism » sobota, 1 czerwca 2013, 18:49

Akurat ten kod u mnie działa bez zarzutów (testowane na XP i Vista). Pewnie znowu coś źle przeniosłeś, dlatego nie działa ;) Co do tego, że jest już funkcja przyciągania do krawędzi pulpitu - cóż, zaimplementowałem ją tam tylko po to, żeby coś było, dla przykładu. Przyciąganie do innych okien niech sobie sam zaimplementuje.

___
p.s. przykładzie nie podałem kodu, który podmienia procedury (ów subclassing). To tak dla jasności. Bardziej ogarnięty programator nie powinien mieć problemu z użyciem tego kodu i z zaimplementowaniem go do własnych potrzeb. W razie czego pytać.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Lepkie formularze

Nowy postprzez polymorphism » sobota, 1 czerwca 2013, 23:23

przeciąganiu pozostają artefakty po przeciąganym oknie

U mnie takich rzeczy nie ma, wszystko jest jak trzeba. Zresztą nie wiem, co mój kod miałby wspólnego ze złym odmalowywaniem okien innych aplikacji.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Lepkie formularze

Nowy postprzez Cyfrowy Baron » niedziela, 2 czerwca 2013, 00:10

To nie jest problem z oknem innej aplikacji lecz z oknem aplikacji z twoim kodem.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Lepkie formularze

Nowy postprzez Cyfrowy Baron » środa, 5 czerwca 2013, 17:50

Niestety firma cal.pl miała jakieś problemy z serwerem, a jako, że nie zrobiłem kopi zapasowej bazy danych, to część postów zniknęła. Niestety nic na to już nie poradzę. Problem został rozwiązany. Zamieszczę ostatni kod jaki mam:

KOD cpp:     UKRYJ  
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit2.h"
#include "Unit1.h"

#include "Windowsx.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm2 *Form2;
//---------------------------------------------------------------------------
__fastcall TForm2::TForm2(TComponent* Owner)
        : TForm(Owner)
{



}
//---------------------------------------------------------------------------
WNDPROC oldWindowProc = NULL;
int     xWndOffset;
int     yWndOffset;
bool    isDragging = false;
int     snapThreshold = 100;

void moveSnapWindow(HWND hwnd, int x, int y)
{
                int snapThreshold_L = Form1->Left + Form1->Width + snapThreshold;
                int snapThreshold_T = Form1->Top + Form1->Height + snapThreshold;
        RECT rc;

        GetWindowRect(hwnd, &rc);

                int scr_w = Form1->Width + Form1->Left;//GetSystemMetrics(SM_CXSCREEN);
                int scr_h = Form1->Height + Form1->Top;//GetSystemMetrics(SM_CYSCREEN);

                if(abs(x) < snapThreshold) x = 0;
                if(abs(y) < snapThreshold) y = 0;
                if(abs(scr_w - (x + rc.right - rc.left)) < snapThreshold_L) x = scr_w;// - (rc.right - rc.left);
                if(abs(scr_h - (y + rc.bottom - rc.top)) < snapThreshold) y = scr_h - (rc.bottom - rc.top);

                MoveWindow(hwnd, x, y, rc.right - rc.left, rc.bottom - rc.top, TRUE);
}

LRESULT CALLBACK newWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
        if(msg == WM_NCLBUTTONDOWN && wParam == HTCAPTION)
        {
                RECT rc;

                GetWindowRect(hwnd, &rc);

                xWndOffset = GET_X_LPARAM(lParam) - rc.left;
                yWndOffset = GET_Y_LPARAM(lParam) - rc.top;

                SetCapture(hwnd);
                isDragging = true;
                return 0;
        }


        if(isDragging && msg == WM_MOUSEMOVE)
        {
                POINT pt = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
                ClientToScreen(hwnd, &pt);
                moveSnapWindow(hwnd, pt.x - xWndOffset, pt.y - yWndOffset);
                return 0;
        }

        if(isDragging && msg == WM_LBUTTONUP)
        {
                isDragging = false;
                if(hwnd == GetCapture())
                        ReleaseCapture();

                POINT pt = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
                ClientToScreen(hwnd, &pt);
                moveSnapWindow(hwnd, pt.x - xWndOffset, pt.y - yWndOffset);
                return 0;
        }

        if(isDragging && msg == WM_CAPTURECHANGED)
        {
                isDragging = false;
        }

        return CallWindowProc(oldWindowProc, hwnd, msg, wParam, lParam);
}




void __fastcall TForm2::FormCreate(TObject *Sender)
{
        oldWindowProc = (WNDPROC) GetWindowLongPtr(Handle, GWLP_WNDPROC);
        SetWindowLongPtr(Handle, GWLP_WNDPROC, (LONG_PTR) &newWindowProc);
}
//---------------------------------------------------------------------------


Prośba do polymorpohism, żeby jeszcze raz zamieścił swój ostatni kod, bo nie mam jego kopii, a komuś może się przydać.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Lepkie formularze

Nowy postprzez polymorphism » środa, 5 czerwca 2013, 18:03

Modyfikacja moveSnapWindow:
KOD cpp:     UKRYJ  
enum
{
        OXEdgesOverlap = 1,
        OYEdgesOverlap
};

int checkEdgesOverlapping(const RECT &rc1, const RECT &rc2)
{
        int res = 0;
       
        if(rc1.top <= rc2.top)
        {
                if(rc1.bottom > rc2.top) res = OYEdgesOverlap;
        }
        else
        {
                if(rc2.bottom > rc1.top) res = OYEdgesOverlap;
        }
       
        if(rc1.left <= rc2.left)
        {
                if(rc1.right > rc2.left) res |= OXEdgesOverlap;
        }
        else
        {
                if(rc2.right > rc1.left) res |= OXEdgesOverlap;
        }
       
        return res;
}


void moveSnapWindow(HWND hwnd, int x, int y)
{
        RECT rc1, rc2;

        GetWindowRect(hwnd_2, &rc1);
       
        GetWindowRect(hwnd, &rc2);

        OffsetRect(&rc2, x - rc2.left, y - rc2.top);

        int overlap = checkEdgesOverlapping(rc1, rc2);
        int dx = 0, dy = 0;

        if(overlap & OYEdgesOverlap)
        {
                if(abs(dx = rc1.right - rc2.left) > snapThreshold)
                        if(abs(dx = rc1.left - rc2.right) > snapThreshold) dx = 0;
        }

        if(overlap & OXEdgesOverlap)
        {
                if(abs(dy = rc1.bottom - rc2.top) > snapThreshold)
                        if(abs(dy = rc1.top - rc2.bottom) > snapThreshold) dy = 0;
        }

        OffsetRect(&rc2, dx, dy);

        MoveWindow(hwnd, rc2.left, rc2.top, rc2.right - rc2.left, rc2.bottom - rc2.top, TRUE);
}

hwnd_2 to okno, do którego ma się przyciągać przeciągane okno.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Poprzednia strona

  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

Powrót do Ogólne problemy z programowaniem

Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 4 gości