[C++ Builder] borderless form resizen

Pagina: 1
Acties:

  • Schmoove
  • Registratie: Juli 2001
  • Laatst online: 22:53
Ik ben al een tijdje bezig om een DU Meter clone te maken en het het is voor een deel al aardig werkend.
Nu heb ik een probleem met het form wat ik gebruik. Ik heb het form borderless gemaakt (borderstyle = bsNone), maar nu is het form niet meer te resizen.
Dit wist ik wel van te voren natuurlijk, maar het is altijd de bedoeling geweest om het alsnog resizable te maken..... dit lukt alleen voor geen meter.
Heb verschillende dingen geprobeerd, overal gezocht, maar niks dat me echt de goede richting in hielp.
Kan iemand me hier een beetje mee op weg helpen?

Om het wat duidelijker te maken heb ik een executable van het programma online gezet. Voor de duidelijkheid het gaat dus om het main form. Je kan het wel verslepen, maar (nog) niet resizen.

http://users.skynet.be/bk265512/netmon.zip

  • Schmoove
  • Registratie: Juli 2001
  • Laatst online: 22:53
Helemaal niemand die mij hiermee kan helpen?

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

Ik snap je probleem niet helemaal... je hebt het ding expliciet borderless gemaakt terwijl je wist dat dat 'm unsizeable zou maken, dus wat wil je nu?

Professionele website nodig?


  • alienfruit
  • Registratie: Maart 2003
  • Laatst online: 26-05 11:18

alienfruit

the alien you never expected

Mja, je zou wat message-en kunnen opvangen in bijv. WM_SETCURSOR en kijken waar de muis is en dan die verschillende pijltjes cursors laten zien. Vervolgens gebruik je de LMOUSEDOWN-message (naam klopt volgens mij niet) om het venster te vergroten/verkleinen.

Trouwens misschien kan je ook proberen om een resizable borderstyle te pakken waarbij je de caption onzichtbaar maakt en vervolgens haal je in WM_NCPAINT de border weg. Geen idee of beidde ideenen in het echt werken :+

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

alienfruit schreef op 23 februari 2004 @ 11:49:
Geen idee of beidde ideenen in het echt werken :+
Yup, allebei perfect werkend, alhoewel ik zelf voor optie 1 zou kiezen :)

Professionele website nodig?


  • Schmoove
  • Registratie: Juli 2001
  • Laatst online: 22:53
curry684 schreef op 23 februari 2004 @ 10:59:
Ik snap je probleem niet helemaal... je hebt het ding expliciet borderless gemaakt terwijl je wist dat dat 'm unsizeable zou maken, dus wat wil je nu?
Het gaat erom dat ik die border niet wil zien en het form wel resizable wil houden. Of dat nou tegen de zin van het bestaan van (borderstyle) bsNone in gaat kan me eigenlijk helemaal niks schelen. Ik wil het zo, dus dat is voor mij genoeg reden om het zo te doen. Daarnaast weet ik gewoon zeker dat het mogelijk is.... het is alleen een kwestie van slim implementeren.
Mja, je zou wat message-en kunnen opvangen in bijv. WM_SETCURSOR en kijken waar de muis is en dan die verschillende pijltjes cursors laten zien. Vervolgens gebruik je de LMOUSEDOWN-message (naam klopt volgens mij niet) om het venster te vergroten/verkleinen.

Trouwens misschien kan je ook proberen om een resizable borderstyle te pakken waarbij je de caption onzichtbaar maakt en vervolgens haal je in WM_NCPAINT de border weg. Geen idee of beidde ideenen in het echt werken
Die eerste oplossing heb ik al geprobeerd, maar wil de niet echt lukken. Ik denk wel dat dat inderdaad de beste oplossing is, maar het vinden van de juiste code wil niet echt lukken zoals ik al zei, het groter maken van het form ging best, maar het form vervolgens weer verkleinen ging niet lekker. Daarom vroeg ik mij af of iemand hier toevallig een stuk goed werkende code voor had.

Trouwens wat het afvangen van messages betreft. Hoe gaat dat precies??
Ik heb eigenlijk geen idee waar die berichten binnenkomen en hoe je ze afvangt.
Zou je me dat duidelijk kunnen maken met een voorbeeld ofzo?

Mocht het helemaal niet lukken, dan ga ik gewoon het form laten resizen mbv de pijltjes toetsen... voorlopig dan.

Alvast bedankt in iedergeval voor de hulp.

[ Voor 13% gewijzigd door Schmoove op 23-02-2004 12:21 ]


  • Reptile209
  • Registratie: Juni 2001
  • Laatst online: 23:53

Reptile209

- gers -

Schmoove schreef op 23 februari 2004 @ 12:06:
Die eerste oplossing heb ik al geprobeerd, maar wil de niet echt lukken. Ik denk wel dat dat inderdaad de beste oplossing is, maar het vinden van de juiste code wil niet echt lukken zoals ik al zei, het groter maken van het form ging best, maar het form vervolgens weer verkleinen ging niet lekker. Daarom vroeg ik mij af of iemand hier toevallig een stuk goed werkende code voor had.
Zo uit mijn hoofd gaat het waarschijnlijk mis bij het opnieuw tekenen van het form na het verkleinen. Bij het vergroten valt dat minder op (want je maakt meer ruimte...). Probeer eens om, na het verkleinen van het form met Width en Height, een Form.Invalidate aan te roepen. Die zorgt dan dat de boel weer opnieuw getekend wordt.
Als dat het niet is, leg dan eens uit wat er wel misgaat :).
Trouwens wat het afvangen van messages betreft. Hoe gaat dat precies??
Ik heb eigenlijk geen idee waar die berichten binnenkomen en hoe je ze afvangt.
Zou je me dat duidelijk kunnen maken met een voorbeeld ofzo?
Messages kan je afvangen door het overriden van de WndProc-procedure. Via GetMessage(), TranslateMessage() en DispatchMessage() kan je messages bekijken en verwerken. F1-werk, want dat heb ik alleen een keer in Delphi gedaan... :)
* is niet zo'n C++-er

Zo scherp als een voetbal!


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

En toch is er niets moeilijk aan: override de MouseMove van je form zodat je op de buitenste 2-3 pixels de goede cursors zet, bij een MouseDown in dat gebied lock je de cursor, capture je de muis met 'SetCapture', bij MouseUp release je hem indien locked, en zolang locked doe je met SetBounds in 1 klap de nieuwe coordinaten zetten. En klaar is Klara, werkt perfect zonder eigen messagepumps en alles.

Maar met 'hijdoetutnie' kunnen we niet veel, wat ging er fout bij jou? :)

Professionele website nodig?


  • Schmoove
  • Registratie: Juli 2001
  • Laatst online: 22:53
Reptile209 schreef op 23 februari 2004 @ 13:54:
[...]

Zo uit mijn hoofd gaat het waarschijnlijk mis bij het opnieuw tekenen van het form na het verkleinen. Bij het vergroten valt dat minder op (want je maakt meer ruimte...). Probeer eens om, na het verkleinen van het form met Width en Height, een Form.Invalidate aan te roepen. Die zorgt dan dat de boel weer opnieuw getekend wordt.
Als dat het niet is, leg dan eens uit wat er wel misgaat :).

[...]

Messages kan je afvangen door het overriden van de WndProc-procedure. Via GetMessage(), TranslateMessage() en DispatchMessage() kan je messages bekijken en verwerken. F1-werk, want dat heb ik alleen een keer in Delphi gedaan... :)
* is niet zo'n C++-er
Het ging niet zo zeer fout op die invalidate, dat was het probleem niet.
Ik had het namelijk als volgt gedaan. Ik ben gaan checken bij elke mousemove op welke plek boven het form de cursor zweeft. Als de cursor zich binnen een grens van 5 pixels van de rand van het form bevond dan veranderde ik de cursor in een resize arrow (horizontaal, diagonaal dan wel verticaal). Dit werkte allemaal prima.
Dan bij een mouse down zet ik een variabele op true die aangeeft dat het form geresized moet worden bij een nieuwe mousemove. In de OnMouseMove functie reken ik dan het verschil tussen twee mousemoves uit, dit verschil is precies de hoeveelheid die het form moet groeien, dan wel krimpen.
Als je de rechter kant van het form naar rechts trekt, dan werd het form ook netjes groter. Echter bij het verkleinen van het form ging het fout. De mousemove functie was niet echt helemaal goed denk ik want op een gegeven moment als je de muis naar links beweegt dan kom je automatisch weer uit het gebied van 5 pixels van de rand... waardoor het verkleinen dus ge-abort wordt en er rare effecten optreden.

Ik denk dat ik nu wel ongeveer weet hoe ik het moet implementeren. Ga het vanavond nog maar eens proberen en kijken of het een beetje wil lukken.
Mocht het lukken dan plaats ik de code hier wel zodat anderen er misschien nog baat bij hebben.

Nog bedankt voor die WndProc hint, ben er uit hoe ik messages af moet vangen. Ik weet nog niet of ik het ga gebruiken, maar de kennis is nooit weg. Bedankt daarvoor :)

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

Schmoove schreef op 23 februari 2004 @ 14:20:
[...]
Echter bij het verkleinen van het form ging het fout. De mousemove functie was niet echt helemaal goed denk ik want op een gegeven moment als je de muis naar links beweegt dan kom je automatisch weer uit het gebied van 5 pixels van de rand... waardoor het verkleinen dus ge-abort wordt en er rare effecten optreden.
• Zet een boolean 'InResize' tijdens de MouseDown en clear 'm tijdens de MouseUp: tijdens het resizen boeit die 5 pixel grens je niet en mag je er niet naar kijken, anders vernuekt snel bewegen je operatie.
• Gebruik SetCapture om de muis te 'vangen' voor je form, op dat moment krijg je altijd alle mousemoves ook als de muis zich elders beweegt. Release 'm in de MouseUp.
• Doe bij iedere MouseMove alle 4 hoekpunten herberekenen en zet die in 1 keer met SetBounds: dat scheelt je een hoop geflikker en overbodige repaints.
Nog bedankt voor die WndProc hint, ben er uit hoe ik messages af moet vangen. Ik weet nog niet of ik het ga gebruiken, maar de kennis is nooit weg. Bedankt daarvoor :)
Nogmaals: dat heb je niet nodig hiervoor :)

Professionele website nodig?


  • epic007
  • Registratie: Februari 2004
  • Laatst online: 11-03 09:21
kijk eens naar de message WM_NCHITTEST

bijvoorbeeld op MSDN.

  • schoene
  • Registratie: Maart 2003
  • Laatst online: 27-05 15:39
ik raad je sterk aan naar curry684 te luisteren! Ik heb, gewoon uit interesse zijn oplossing eens geprobeerd, en in geen tijd had ik een perfect werkend testprogramma'tje. Zijn uitleg is compleet, dus het zou geen probleem mogen geven.

kheb weer iets bijgeleerd :)

  • alienfruit
  • Registratie: Maart 2003
  • Laatst online: 26-05 11:18

alienfruit

the alien you never expected

Zou moeten werken nu hoor ;)

  • alienfruit
  • Registratie: Maart 2003
  • Laatst online: 26-05 11:18

alienfruit

the alien you never expected

Sorry, dat de code in delphi is maar dit werkende code. Om een borderless window te resize-en en te verplaatsen. JE moet natuurlijk wel je Form definitie de WMNCHITTEST overriden dmv.:

procedure WMNCHITTEST( var Msg: TWMNCHITTEST ); message WM_NCHITTEST;

Veel plezier ermee!

Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
procedure TForm1.WMNCHITTEST(var Msg: TWMNCHITTEST);
var
  aPoint, cltPoint: TPoint;
const
  RESIZE_HITSPOT = 5;
begin
  aPoint.X := Msg.XPos;
  aPoint.Y := Msg.YPos;
  cltPoint := ScreenToClient( aPoint );

  // check left
  if ( cltPoint.X < RESIZE_HITSPOT ) then
    Msg.Result := HTLEFT
  else if ( cltPoint.X + RESIZE_HITSPOT >= ClientWidth  ) then
    Msg.Result := HTRIGHT;

  // check right
  if ( cltPoint.Y < RESIZE_HITSPOT ) then
    Msg.Result := HTTOP
  else if ( cltPoint.Y + RESIZE_HITSPOT >= ClientHeight  ) then
    Msg.Result := HTBOTTOM;

  if ( cltPoint .X < RESIZE_HITSPOT ) and ( cltPoint.Y < RESIZE_HITSPOT )  then
      Msg.Result := HTTOPLEFT
  else if (cltPoint.X +  RESIZE_HITSPOT >= ClientWidth ) and ( cltPoint.Y < RESIZE_HITSPOT )  then
      Msg.Result := HTTOPRIGHT;

  if ( cltPoint .X < RESIZE_HITSPOT ) and ( cltPoint.Y +  RESIZE_HITSPOT > ClientHeight ) then
      Msg.Result := HTBOTTOMLEFT
  else if ( cltPoint.X +  RESIZE_HITSPOT >= ClientWidth ) and ( cltPoint.Y +  RESIZE_HITSPOT > ClientHeight )  then
      Msg.Result := HTBOTTOMRIGHT;

  // make it moveable when the original result is HTNOWHERE
  if ( Msg.Result = HTNOWHERE ) then
    Msg.Result := HTCAPTION; // make it movable (whole area actions as the captionbar)
end;

  • Schmoove
  • Registratie: Juli 2001
  • Laatst online: 22:53
Bedankt voor de hulp.
Het is gelukt. Ik heb mijn form resizable gekregen en het werkt precies zoals ik het wil. Thanks :)

Ik heb de code van alienfruit gebruikt en ik moet zeggen het is brilliant!! Werkt echt geweldig :)
Ik zal nog even de C++ vertaling geven voor de volledigheid:

In de header file:
code:
1
2
3
4
5
6
private:    // User declarations
  void __fastcall WMNCHitTest(TMessage& Msg);

  BEGIN_MESSAGE_MAP
    MESSAGE_HANDLER(WM_NCHITTEST, TMessage, WMNCHitTest)
  END_MESSAGE_MAP(TForm)


In de cpp file:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
void __fastcall TForm1::WMNCHitTest(TMessage& Msg)
{
  TPoint aPoint, cltPoint;
  int RESIZE_HITSPOT = 5;

  aPoint.x = Msg.LParamLo;
  aPoint.y = Msg.LParamHi;

  cltPoint = ScreenToClient( aPoint );

  // check left
  if( cltPoint.x < RESIZE_HITSPOT )
    Msg.Result = HTLEFT;
  else if ( cltPoint.x + RESIZE_HITSPOT >= ClientWidth  )
    Msg.Result = HTRIGHT;

  // check right
  if ( cltPoint.y < RESIZE_HITSPOT )
    Msg.Result = HTTOP;
  else if ( cltPoint.y + RESIZE_HITSPOT >= ClientHeight  )
    Msg.Result = HTBOTTOM;

  if (( cltPoint.x < RESIZE_HITSPOT ) && ( cltPoint.y < RESIZE_HITSPOT ))
      Msg.Result = HTTOPLEFT;
  else if ((cltPoint.x +  RESIZE_HITSPOT >= ClientWidth ) && ( cltPoint.y < RESIZE_HITSPOT ))
      Msg.Result = HTTOPRIGHT;

  if (( cltPoint.x < RESIZE_HITSPOT ) && ( cltPoint.y +  RESIZE_HITSPOT > ClientHeight ))
      Msg.Result = HTBOTTOMLEFT;
  else if (( cltPoint.x +  RESIZE_HITSPOT >= ClientWidth ) && ( cltPoint.y +  RESIZE_HITSPOT > ClientHeight ))
      Msg.Result = HTBOTTOMRIGHT;

  // make it moveable when the original result is HTNOWHERE
  if ( Msg.Result == HTNOWHERE )
    Msg.Result = HTCAPTION; // make it movable (whole area actions as the captionbar)
}

[ Voor 88% gewijzigd door Schmoove op 24-02-2004 09:16 ]


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

schoene schreef op 23 februari 2004 @ 17:24:
ik raad je sterk aan naar curry684 te luisteren! Ik heb, gewoon uit interesse zijn oplossing eens geprobeerd, en in geen tijd had ik een perfect werkend testprogramma'tje. Zijn uitleg is compleet, dus het zou geen probleem mogen geven.
O+

Professionele website nodig?

Pagina: 1