Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Sheddex

unregistriert

1

07.10.2007, 15:07

WINAPI Kapselung: Plötzliche Variablenänderung

Eins vorweg: Seid so gut und schreibt nicht irgendwas in der Art wie "Es gibt schon Kapselungen, verwende doch einfach diese.". Ich will einfach meine eigene schreiben... aber das Problem hat eventuell garnichts speziell mit der Kapselung zu tun...

Also, das Problem:
Ich habe eine std::map, die Strukturen von Typ "ComboBox" speichert. Diese Struktur enthält unter Anderem eine Variable namens "Changed". Diese ist true, falls ein anderes Element in der ComboBox ausgewählt wurde.
Zu Beginn der Fensterprozedur wird die Change-Variable eines jeden Map-Elements auf false gesetzt. Später in WM_COMMAND wird eine solche Variable auf true gesetzt, falls den eine Änderung stattfand.
Hier nun erstmal der wichtige Code der Prozedur:

C-/C++-Quelltext

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
LRESULT Dmd::Window::Proc(HWND Window, UINT Message, WPARAM WParam, LPARAM LParam)
{
  for (std::map<std::wstring, ComboBox>::iterator i = ComboBoxes.begin(); i != ComboBoxes.end(); ++i)
    i->second.Changed = false;

  switch (Message)
  {
    case WM_COMMAND:
    {
      for (std::map<std::wstring, ComboBox>::iterator i = ComboBoxes.begin(); i != ComboBoxes.end(); ++i)
      {
        if (LParam == reinterpret_cast<LPARAM>(i->second.Handle) && HIWORD(WParam) == CBN_SELCHANGE)
          i->second.Changed = true;

        if (i->second.Changed == true)
          ::MessageBoxW(NULL, L"Changed ist true", L"Info 1", MB_OK);

        if (i->second.Changed == true)
          ::MessageBoxW(NULL, L"Changed ist true", L"Info 2", MB_OK);
      }
    } break;
  }

  return 0;
}


Das Probleme ist hier nun, dass Changed irgendwie einfach nicht true bleibt. Die erste Box wird angezeigt, die zweite allerdings nicht. Woran könnte das liegen?
Das "Lustige" ist außerdem: Genau so mache ich das auch bei den List Boxen, nur bei denen geht es...
Hat jemand eine Idee, woran es liegen könnte, dass true plötzlich false wird?...

2

07.10.2007, 15:47

Hmm also 1. sollte man nicht i++ sondern ++i nutzen :P Dann geh mal in den Debugger und guck ob du dir vorher irgendwo nen Speicher zuhaust ...
Devil Entertainment :: Your education is our inspiration
Der Spieleprogrammierer :: Community Magazin
Merlin - A Legend awakes :: You are a dedicated C++ (DirectX) programmer and you have ability to work in a team? Contact us!
Siedler II.5 RttR :: The old settlers-style is comming back!

Also known as (D)Evil

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

3

07.10.2007, 15:56

Dann setz halt nicht jedesmal alle Einträge auf "false"... Wozu brauchst du egtl 2 Boxen?
@D13_Dreinig

Sheddex

unregistriert

4

07.10.2007, 16:22

@Deviloper: 1. Warum? 2. Nein tue ich nicht, wobei ich auch nicht wirklich weiß was du genau meinst.

@David_pb: Sie müssen doch irgendwo auf false gesetzt werden.
Ich kann das natürlich auch so machen (ist auch viel schöner):

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
for (std::map<std::wstring, ComboBox>::iterator i = ComboBoxes.begin(); i != ComboBoxes.end(); ++i)
{
  if (LParam == reinterpret_cast<LPARAM>(i->second.Handle) && HIWORD(WParam) == CBN_SELCHANGE)
    i->second.Changed = true;

  else
    i->second.Changed = false;

  if (i->second.Changed == true)
    ::MessageBoxW(NULL, L"Changed ist true", L"Info 1", MB_OK);

  if (i->second.Changed == true)
    ::MessageBoxW(NULL, L"Changed ist true", L"Info 2", MB_OK);
}


Ändert aber nichts am Resultat...

Und warum soll ich keine zwei Boxen brauchen? VS hat auch 3, die man sofort sieht...

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

5

07.10.2007, 16:28

Zitat von »"DragonFlame"«

1. Warum?


Weil preinkrement Operator ist hier schneller weil keine Kopie von Objekt erzeugt werden muss.

Zitat von »"DragonFlame"«


2. Nein tue ich nicht, wobei ich auch nicht wirklich weiß was du genau meinst.


So kannst du feststellen ob du evtl ungewollt Speicher überschreibst.

Zitat von »"DragonFlame"«


@David_pb: Sie müssen doch irgendwo auf false gesetzt werden.
Ich kann das natürlich auch so machen (ist auch viel schöner):

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
for (std::map<std::wstring, ComboBox>::iterator i = ComboBoxes.begin(); i != ComboBoxes.end(); ++i)
{
  if (LParam == reinterpret_cast<LPARAM>(i->second.Handle) && HIWORD(WParam) == CBN_SELCHANGE)
    i->second.Changed = true;

  else
    i->second.Changed = false;

  if (i->second.Changed == true)
    ::MessageBoxW(NULL, L"Changed ist true", L"Info 1", MB_OK);

  if (i->second.Changed == true)
    ::MessageBoxW(NULL, L"Changed ist true", L"Info 2", MB_OK);
}


Schön ist das auch nicht, aber wenns zweckmäßig ist... Wieso nicht?!

Zitat von »"DragonFlame"«


Ändert aber nichts am Resultat...


So?

Zitat von »"DragonFlame"«


Und warum soll ich keine zwei Boxen brauchen? VS hat auch 3, die man sofort sieht...


Reden wir von den gleichen Boxen? Ich mein die Message Boxen. Und mir ist immer noch schleierhaft wieso du zwei brauchst! :-P
@D13_Dreinig

Sheddex

unregistriert

6

07.10.2007, 16:38

Ach so, ich dachte du meinst, dass es sinnlos ist, mehrere Comboboxen zu verwenden ;)

Ich brauche an der Stelle eigentlich garkeine MessageBox, ich habe sie da hingebaut, da meine CB_HasChanged-Methode immer false geliefert hat...
Und selbst wenn ich sie brauche: Es sollte doch trotzdem gehen.

Mir ist aufgefallen, dass das mit dem else so doch nicht geht, da ja auch auf false gesetzt werden soll, wenn die Nachricht nicht WM_COMMAND ist.
Das i++ ändere ich mal im Startpost.

Nox

Supermoderator

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

7

07.10.2007, 16:46

Ganz sicher, dass es so bei den ListBoxen funktioniert?

Weil es kann sein, dass durch die MessageBox eine Nachricht ans Fenster geschickt wird. Wenn dies der Fall ist, wird allerdings die Varible unter umständen zurückgesetzt.

Versuch doch mal folgendes:

hau beim ersten MessageBoxaufruf ein Haltepunkt rein und dann wenn er da angehalten hat auch bei der SChleife, oder noch besser du bauchst nur bei der Schleife einen Haltepunkt mit der Bedingung Change == true ein.
PRO Lernkurs "Wie benutze ich eine Doku richtig"!
CONTRA lasst mal die anderen machen!
networklibbenc - Netzwerklibs im Vergleich | syncsys - Netzwerk lib (MMO-ready) | Schleichfahrt Remake | Firegalaxy | Sammelsurium rund um FPGA&Co.

Sheddex

unregistriert

8

07.10.2007, 17:16

Ich habe die Message Boxen jetzt einfach mal ganz entfernt und rufe sie nur in der Hauptschleife auf.
Hier übrigens nochmal mit den Listboxen:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
for (std::map<std::wstring, ListBox>::iterator i = ListBoxes.begin(); i != ListBoxes.end(); ++i)
{
  if (LParam == reinterpret_cast<LPARAM>(i->second.Handle) && HIWORD(WParam) == LBN_SELCHANGE)
    i->second.Changed = true;
}

for (std::map<std::wstring, ComboBox>::iterator i = ComboBoxes.begin(); i != ComboBoxes.end(); ++i)
{
  if (LParam == reinterpret_cast<LPARAM>(i->second.Handle) && HIWORD(WParam) == CBN_SELCHANGE)
    i->second.Changed = true;
}


Hier der Ausschnitt aus der Hauptschleife:

C-/C++-Quelltext

1
2
3
4
5
if (Window.CB_HasChanged(L"TestComboBox"))
  ::MessageBoxW(NULL, L"ComboBox has changed", NULL, 0);

if (Window.LB_HasChanged(L"TestListBox"))
  ::MessageBoxW(NULL, L"ListBox has changed", NULL, 0);


Ändert man die Auswahl in der ComboBox passiert wieder nichts, ändert man sie in der ListBox erscheint die MessageBox...

Nox

Supermoderator

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

9

07.10.2007, 17:25

if (LParam == reinterpret_cast<LPARAM>(i->second.Handle) && HIWORD(WParam) == LBN_SELCHANGE)
i->second.Changed = true;

wird aber erfüllt?

Was ist mit dieser Zurücksetzschleife? Wo ist die?
PRO Lernkurs "Wie benutze ich eine Doku richtig"!
CONTRA lasst mal die anderen machen!
networklibbenc - Netzwerklibs im Vergleich | syncsys - Netzwerk lib (MMO-ready) | Schleichfahrt Remake | Firegalaxy | Sammelsurium rund um FPGA&Co.

10

07.10.2007, 17:39

Zitat

@Deviloper: 1. Warum?

http://www.parashift.com/c++-faq-lite/operator-overloading.html#faq-13.15
Devil Entertainment :: Your education is our inspiration
Der Spieleprogrammierer :: Community Magazin
Merlin - A Legend awakes :: You are a dedicated C++ (DirectX) programmer and you have ability to work in a team? Contact us!
Siedler II.5 RttR :: The old settlers-style is comming back!

Also known as (D)Evil

Werbeanzeige