PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Hell on Earth oder win32 Programmierung


Matrix316
2003-11-06, 18:32:04
Neue Woche neues Thema. ;D

Also ich hab hier ein relativ einfaches Fenster in dem ein Icon geladen werden soll. Beim compilieren gibts keine Fehler und ausgeführt wird das Programm nur wird das Icon nicht angezeigt...

Hier mal der Quelltext:


#include <windows.h>
#include "resource.h"

const char Fenster[] = "WinFenster";

LRESULT CALLBACK WndProcedure(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
char text[]="Ein Fenster was ich selbst geschrieben habe!";

switch(iMsg)
{
case WM_PAINT:
hDC=BeginPaint(hWnd,&ps);
TextOut(hDC,10,30,text,strlen(text));
EndPaint(hWnd,&ps);
break;
case WM_CLOSE:
DestroyWindow(hWnd);
break;

case WM_DESTROY:
PostQuitMessage(0);
break;
}

return DefWindowProc(hWnd, iMsg, wParam, lParam);
}

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCms)
{
WNDCLASSEX wndClass;
HWND hWnd;
MSG Msg;

wndClass.cbSize=sizeof(WNDCLASSEX);
wndClass.style=CS_HREDRAW|CS_VREDRAW;
wndClass.lpfnWndProc=WndProcedure;
wndClass.cbClsExtra=0;
wndClass.cbWndExtra=0;
wndClass.hInstance=hInstance;
//wndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
wndClass.hIcon=(HICON)LoadImage(hInstance,MAKEINTRESOURCE(IDI_ICON1),IMAGE_ICON, 0,0,LR_DEFAULTSIZE);
wndClass.hCursor=LoadCursor(NULL, IDC_ARROW);
wndClass.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
wndClass.lpszMenuName=NULL;
wndClass.lpszClassName=Fenster;
wndClass.hIconSm=LoadIcon(NULL, IDI_APPLICATION);

if (!RegisterClassEx(&wndClass))
{
MessageBox(NULL, "Hallo Fehler", 0,0);
return -1;
}

hWnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
Fenster,
"Hallo Fenster",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
640,
480,
NULL,
NULL,
hInstance,
NULL);

if(hWnd == NULL)
{
MessageBox(NULL, "Window Creation Failed!", "Error!",0);
return 0;
}

ShowWindow(hWnd, nShowCms);
UpdateWindow(hWnd);




while(GetMessage(&Msg, NULL, 0, 0))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}

return 0;


}



Ich hoffe jemand kann was damit anfangen. ;)

Crushinator
2003-11-06, 19:03:08
Auf die schnelle fällt mir nur dies ein:

SendMessage(hWnd, WM_SETICON,
(WPARAM)ICON_BIG,
(LPARAM)LoadIcon(hInstance, "IDI_ICON1"));
/* vor dem */
ShowWindow(hWnd, nShowCms);

Matrix316
2003-11-06, 19:31:45
Ahaaa...muss man das für alle Menüs, Icons etc machen?

Dann noch eine Frage:

Wenn man mit dem Ressourcen Editor ein Icon, Menü etc. macht, wird jedesmal eine neue header Datei erstellt die die alte überschreiben will. Was muss man machen, damit man gleichzeitig ein Menü, ein Icon etc. erstellen kann ohne, dass immer die resource.h Datei überschrieben wird?

Crushinator
2003-11-06, 19:51:48
Original geschrieben von Matrix316
Ahaaa...muss man dass für alle Menüs, Icons etc machen? Nein, ich hatte gerade nur das o.g. im Kopf. :freak: Eigentlich funktioniert auch Deine Methode, man muß es nur richtig (http://www.winprog.org/tutorial/menus.html) machen. =)

wndClass.hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON1));
wndClass.hIconSm = (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON1),
IMAGE_ICON, 16, 16, 0);
Wenn man mit dem Ressourcen Editor ein Icon, Menü etc. macht, wird jedesmal eine neue header Datei erstellt die die alte überschreiben will. Was muss man machen, damit man gleichzeitig ein Menü, ein Icon etc. erstellen kann ohne, dass immer die resource.h Datei überschrieben wird? Wenn Du schon all diese Dinge mit dem Ressource-Editor erstellst, sollte doch egal sein ob sie immer wieder (wegen automatischer Nummerierung der Ressourcen) neuerstellt oder nicht? :gruebel:

Matrix316
2003-11-06, 20:05:56
1. Die Zeile von mir ist ja auch aus einem Tutorial ;D nur anscheinend nicht richtig kopiert. :D

2. Nur dann findet er die definition nicht, weil ja jede Header Datei anders aussieht...oder?

Matrix316
2003-11-06, 20:10:54
Hier mal das Tutorial aus dem ich die Zeile übernommen und hab:


WNDCLASSEX wndclassex = {0};

// Fill the WNDCLASSEX fields we care about
wndclassex.cbSize = sizeof(WNDCLASSEX);
wndclassex.style = CS_HREDRAW | CS_VREDRAW;
wndclassex.lpfnWndProc = WinProc;
wndclassex.hInstance = hinstance;
wndclassex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); // Make the window background black
wndclassex.lpszClassName = class_name;
wndclassex.hIcon = (HICON)LoadImage(hinstance,MAKEINTRESOURCE(IDI_ICON1),IMAGE_ICON,0,0,LR_DEFAULTS IZE);

RegisterClassEx(&wndclassex);

hwnd = CreateWindowEx(...

Matrix316
2003-11-06, 20:15:26
Jetzt hab ichs mal geändert:


WNDCLASSEX wndClass;
HWND hWnd;
MSG Msg;

wndClass.cbSize=sizeof(WNDCLASSEX);
wndClass.style=CS_HREDRAW|CS_VREDRAW;
wndClass.lpfnWndProc=WndProcedure;
wndClass.cbClsExtra=0;
wndClass.cbWndExtra=0;
wndClass.hInstance=hInstance;
//wndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
wndClass.hIcon=LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON1));
//wndClass.hIconSm=LoadIcon(NULL, IDI_APPLICATION);
wndClass.hIconSm=(HICON)LoadImage(hInstance,MAKEINTRESOURCE(IDI_ICON1),IMAGE_ICO N,0,0,LR_DEFAULTSIZE);
wndClass.hCursor=LoadCursor(NULL, IDC_ARROW);
wndClass.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
wndClass.lpszMenuName=NULL;
wndClass.lpszClassName=Fenster;

aber ein Icon ist immer noch nicht zu sehen...=)

Wenn es denn angezeigt werden würde, wo würde es dann eigentlich angezeigt werden?

Oder muss der "LoadIcon" Aufruf gar in die Callback Funktion? :|

Crushinator
2003-11-06, 20:27:29
Original geschrieben von Matrix316
(...) 2. Nur dann findet er die definition nicht, weil ja jede Header Datei anders aussieht...oder? Welche Def. meinst Du denn? :kratz2:
Jetzt hab ichs mal geändert: Versuch's doch mal mit

wndClass.hIcon = LoadIcon(hInstance, "IDI_ICON1");
wndClass.hIconSm = (HICON)LoadImage(hInstance, "IDI_ICON1"),
IMAGE_ICON, 16, 16, 0);

oder

wndClass.hIcon = LoadIcon(GetModuleHandle(NULL), "IDI_ICON1");
wndClass.hIconSm = (HICON)LoadImage(GetModuleHandle(NULL), "IDI_ICON1"),
IMAGE_ICON, 16, 16, 0);

Ich glaub' so langsam, es hatte einen Grund, warum ich immer die Variante mit "SendMessage" verwende und sie deshalb auswendig kenne. :D

Wie groß ist denn eigentlich Dein Icon?

Crushinator
2003-11-06, 20:30:09
Original geschrieben von Matrix316
(...)
Oder muss der "LoadIcon" Aufruf gar in die Callback Funktion? :| Nein, das braucht's nicht, es sei denn Du möchtest da bei einem Event die Icons umswitchen.

Matrix316
2003-11-06, 20:31:33
32*32

Das lustige ist, in der Aufgabenstellung steht:


a) Erzeugen Sie ein Win32 Programm, das ein Fenster auf dem Bildschirm anzeigt. (nach dem Grundgerüst wie in der Vorlesung besprochen)

b) Erzeugen Sie im Ressourcen Editor Icons für das Programm, einen Mousecursor, ein Menu, Stringtable.

c) Der Titel des Fensters soll mit Hilfe von LoadString angegeben werden.

c) Durch Click mit der linken Maustaste auf die Bildschirmfläche sollen alle Punkte durch eine Linie verbunden werden. Am letzten Punkt soll die Position des Mauszeigers als Text (in einer anderen Schriftart) ausgegeben werden.

d) Erzeugen Sie in der Ressourcen Datei ein Menü
dessen Menüpunkte in der Callback Funktion abgefragt werden. Es sollen folgende Menüpunkte vorhanden sein: Beenden, Bildschirm löschen, Linienfarbe ändern, Info Dialog

e) Erzeugen Sie über den Ressourcen Editor ein Info Dialog.

f) Der Info Dialog soll weiterhin durch die Tastenkombination ALT-? (also ALT-Shift-?) angezeigt werden. [Acceleratortable verwenden]

g) Bauen Sie das Beispiel TrayIcon in Ihr Programm ein.

und im Skript steht aber nix wie das jetzt gehen soll...

Matrix316
2003-11-06, 20:36:03
Zum header:

Ich mach ja "include "resource.h""

Und da steht der Name drin, den man bei LoadIcon reinschreibt: MAKEINTRESOURCE(IDI_ICON1)

Wenn ich jetzt aber ein Menü mache, wird die Headerdatei überschrieben und er findet "IDI_ICON1" nicht mehr, weil es nicht ja nicht mehr in der neuen "resource.h" steht...

Crushinator
2003-11-06, 20:51:24
Hab' gerade keinen Compiler zur Verfügung und muß dringend los. Jedenfalls mußt Du für "wndClass.hIconSm" auch ein 16x16 Icon haben, sonst tut das nicht gehen, und die Deffinition vom "IDI_ICON1" sollte eigentlich in der .rc stehen oder nicht? :kratz2: Ist auch schon zulange her, daß ich Window-Apps in C und nur mit der API geschrieben habe. Hat denn mein Beispiel mit ohne MAKEINTRESOURCE funktionukkelt?

Erstmal noch viel Spaß beim testen, muß weg. :weg:

Matrix316
2003-11-06, 20:59:01
Original geschrieben von crushinator
Hab' gerade keinen Compiler zur Verfügung und muß dringend los. Jedenfalls mußt Du für "wndClass.hIconSm" auch ein 16x16 Icon haben, sonst tut das nicht gehen, und die Deffinition vom "IDI_ICON1" sollte eigentlich in der .rc stehen oder nicht? :kratz2: Ist auch schon zulange her, daß ich Window-Apps in C und nur mit der API geschrieben habe. Hat denn mein Beispiel mit ohne MAKEINTRESOURCE funktionukkelt?


Leider nicht...Das Fenster ist da, der Text ist da, aber kein Icon...

PS.: Wer die win32 Programmierung erfunden hat, dem sollte man den SACK AUF DEN KÜCHENTISCH NAGELN!!!

PPS.:Jetzt mal eine blöde Frage: Ist das Icon ETWA DAS was links oben im Fenster zu sehen ist??? :bonk: :banghead: :kratz: :bigl2:

Xmas
2003-11-06, 23:15:26
Original geschrieben von Matrix316
PPS.:Jetzt mal eine blöde Frage: Ist das Icon ETWA DAS was links oben im Fenster zu sehen ist??? :bonk: :banghead: :kratz: :bigl2:
Ja, natürlich. Welches Icon hat ein Fenster sonst?

Original geschrieben von Matrix316
Zum header:

Ich mach ja "include "resource.h""

Und da steht der Name drin, den man bei LoadIcon reinschreibt: MAKEINTRESOURCE(IDI_ICON1)

Wenn ich jetzt aber ein Menü mache, wird die Headerdatei überschrieben und er findet "IDI_ICON1" nicht mehr, weil es nicht ja nicht mehr in der neuen "resource.h" steht...
?
Wie genau "machst" du ein Menü? Ich hoffe doch, du erstellst kein neues Resource Script (.rc), sondern fügst das Menü einem bestehenden Script hinzu.

Crushinator
2003-11-07, 12:02:33
So mein lieber Matrixchen, ich sitze jetzt endlich vor meinem VC++ 6 und habe Deinen Code in dieser Form übernommen und poste nur die WinMain:

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCms)
{
WNDCLASSEX wndClass;
HWND hWnd;
MSG Msg;

wndClass.cbSize=sizeof(WNDCLASSEX);
wndClass.style=CS_HREDRAW|CS_VREDRAW;
wndClass.lpfnWndProc=WndProcedure;
wndClass.cbClsExtra=0;
wndClass.cbWndExtra=0;
wndClass.hInstance=hInstance;
wndClass.hIcon=LoadIcon(GetModuleHandle(NULL),MAKEINTRESOURCE(IDI_ICON1));
wndClass.hIconSm = (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON1),
IMAGE_ICON, 16, 16, 0);
wndClass.hCursor=LoadCursor(NULL, IDC_ARROW);
wndClass.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
wndClass.lpszMenuName=NULL;
wndClass.lpszClassName=Fenster;

if (!RegisterClassEx(&wndClass))
{
MessageBox(NULL, "Hallo Fehler", 0,0);
return -1;
}

hWnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
Fenster,
"Hallo Fenster",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
640,
480,
NULL,
NULL,
hInstance,
NULL);

if(hWnd == NULL)
{
MessageBox(NULL, "Window Creation Failed!", "Error!",0);
return 0;
}

ShowWindow(hWnd, nShowCms);
UpdateWindow(hWnd);




while(GetMessage(&Msg, NULL, 0, 0))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}

return 0;

}

Icons sind in 32x32 und 16x16 vorhanden, und in meiner .rc steht folgendes:

IDI_ICON1 ICON DISCARDABLE "icon1.ico"

Tu' mal schauen, was dabei rauskommt. =)

Matrix316
2003-11-07, 12:39:45
Original geschrieben von Xmas
Ja, natürlich. Welches Icon hat ein Fenster sonst?


?
Wie genau "machst" du ein Menü? Ich hoffe doch, du erstellst kein neues Resource Script (.rc), sondern fügst das Menü einem bestehenden Script hinzu.

1. Keine Ahnung, vielleicht irgendeins in der Mitte. ;) BTW, GEHT überhaupt ein 32*32 großes Icon? DAS könnte auch ein Problem sein...=)

2. Natürlich mach ich ein NEUES, weil ansonsten nur "importieren" und "Benutzerdefiniert" zur Auswahl angeboten werden und NICHT einfügen oder sowas...;)

Ehrlich gesagt von Visual Studio hab ich überhaupt keine Ahung, weil ich es bislang nur als quasi Compiler für Quelltexte genutzt habe aber ansonsten nichts.

Hast du den Text selbst in die resource.h eingetragen oder ging das automatisch? Bei mir schreibt der da nur 101 rein. Und wenn ich deinen Text nutze und das was du auch in der resource.h drinnen hast gibts bei mir nur Fehlermeldungen:


--------------------Konfiguration: win32uebung4 - Win32 Debug--------------------
Kompilierung läuft...
win32.cpp
F:\Schnittstellen0304\Uebung4\win32uebung4\win32.cpp(44) : error C2065: 'ICON' : nichtdeklarierter Bezeichner
F:\Schnittstellen0304\Uebung4\win32uebung4\win32.cpp(44) : error C2146: Syntaxfehler : Fehlendes ')' vor Bezeichner 'DISCARDABLE'
F:\Schnittstellen0304\Uebung4\win32uebung4\win32.cpp(44) : error C2059: Syntaxfehler : ')'
F:\Schnittstellen0304\Uebung4\win32uebung4\win32.cpp(45) : error C2146: Syntaxfehler : Fehlendes ')' vor Bezeichner 'DISCARDABLE'
F:\Schnittstellen0304\Uebung4\win32uebung4\win32.cpp(46) : error C2059: Syntaxfehler : ')'
Fehler beim Ausführen von cl.exe.

win32.obj - 5 Fehler, 0 Warnung(en)


Hier die resource.h


//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by Icon.rc
//
#define IDI_ICON1 ICON DISCARDABLE "icon1.ico"

// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 102
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

Crushinator
2003-11-07, 13:58:49
Lies' bitte noch mal :wink: Ich habe .rc geschrieben. In meiner .h steht dagegen auch nur folgendes drinn:

#define IDI_ICON1 101

Das ganze wird bei mir auch automatisch durch den Ressourcen-Editor erzeugt. Der Rest meiner .h Datei ist fast identisch mit Deiner. Wenn ich nur ein 32x32 Icon habe, sieht's oben Links eben viel zu klein aus, weil es auf 16x16 runtergerechnet wird.

Ansonsten, geht das Menü doch auch in der selben Datei hinzuzufügen, indem man rechte Maustaste->Einfügen->Menü auswählen->Neu-Knopf macht, oder verwechsle ich da jetzt was?

Matrix316
2003-11-07, 16:01:07
Also ich hab nochmal nachgesehen: In der .rc stehts so drin wie bei dir, in der .h ebenfalls, im winmain ebenso aber trotzdem macht er es nicht...

Matrix316
2003-11-07, 16:17:51
Hier nochmal alle relevanten Daten:

*.cpp



#include <windows.h>
#include "resource.h"

const char Fenster[] = "WinFenster";

LRESULT CALLBACK WndProcedure(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
char text[]="Ein Fenster was ich selbst geschrieben habe!";

switch(iMsg)
{
case WM_PAINT:
hDC=BeginPaint(hWnd,&ps);
TextOut(hDC,10,30,text,strlen(text));
EndPaint(hWnd,&ps);
break;
case WM_CLOSE:
DestroyWindow(hWnd);
break;

case WM_DESTROY:
PostQuitMessage(0);
break;
}

return DefWindowProc(hWnd, iMsg, wParam, lParam);
}

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCms)
{
WNDCLASSEX wndClass;
HWND hWnd;
MSG Msg;

wndClass.cbSize=sizeof(WNDCLASSEX);
wndClass.style=CS_HREDRAW|CS_VREDRAW;
wndClass.lpfnWndProc=WndProcedure;
wndClass.cbClsExtra=0;
wndClass.cbWndExtra=0;
wndClass.hInstance=hInstance;
wndClass.hIcon=LoadIcon(GetModuleHandle(NULL),MAKEINTRESOURCE(IDI_ICON1));
wndClass.hIconSm = (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON1),
IMAGE_ICON, 16, 16, 0);
wndClass.hCursor=LoadCursor(NULL, IDC_ARROW);
wndClass.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
wndClass.lpszMenuName=NULL;
wndClass.lpszClassName=Fenster;

if (!RegisterClassEx(&wndClass))
{
MessageBox(NULL, "Hallo Fehler", 0,0);
return -1;
}

hWnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
Fenster,
"Hallo Fenster",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
640,
480,
NULL,
NULL,
hInstance,
NULL);

if(hWnd == NULL)
{
MessageBox(NULL, "Window Creation Failed!", "Error!",0);
return 0;
}

ShowWindow(hWnd, nShowCms);
UpdateWindow(hWnd);




while(GetMessage(&Msg, NULL, 0, 0))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}

return 0;

}


resource.h

//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by Icon.rc
//
#define IDI_ICON1 101

// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 102
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

*.rc

//Microsoft Developer Studio generated resource script.
//
#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"

/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS

/////////////////////////////////////////////////////////////////////////////
// Deutsch (Deutschland) resources

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU)
#ifdef _WIN32
LANGUAGE LANG_GERMAN, SUBLANG_GERMAN
#pragma code_page(1252)
#endif //_WIN32

/////////////////////////////////////////////////////////////////////////////
//
// Icon
//

// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_ICON1 ICON DISCARDABLE "icon1.ico"

#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//

1 TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h\0"
END

2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END

3 TEXTINCLUDE DISCARDABLE
BEGIN
"\r\n"
"\0"
END

#endif // APSTUDIO_INVOKED

#endif // Deutsch (Deutschland) resources
/////////////////////////////////////////////////////////////////////////////



#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//


/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED



Ich hatte sogar mal ein Tutorial für ein Icon selbst compiliert und da gings AUCH nicht!!!

:bonk: ich verstehs net...=)

Matrix316
2003-11-07, 16:43:42
Ich hab jetzt sogar ein komplett neues Projekt gemacht. Nur den Hauptquelltext als cpp datei genommen und ein neues Icon gemacht. Aber nix...

Muss man da noch irgendwas extra einstellen oder wie oder was dass er endlich dieses verfi**te Icon einbaut???:motz: :kratz:

Crushinator
2003-11-07, 17:21:49
:troest: Gib mir doch mal bitte Deine eMail-Adresse per PN. Ich schicke Dir dann mein Projekt (3.9 KB) inkl. Icon. Du kompilierst es und siehst ob das funktionukkelt. Wenn dem so ist, stimmt nur was mit Deinem Icon nicht.

Matrix316
2003-11-07, 17:45:43
unterwegs

Am besten inkl ALLEN Dateien (Arbeitsbereich *dsw oder so etc.)

Crushinator
2003-11-07, 17:49:10
unterwegs. :)

Matrix316
2003-11-07, 17:58:41
Hmmmm...geht. :freak: ;)

Kannst du mal probieren ob es bei dir geht, wenn du das Icon selbst malst (über den Ressourcen Editor)?

Macht es eigentlich einen Unterschied ob das File *.c oder *.cpp heißt?

Also ich hab mal vergleichen die *c/*.cpp, die *.h und die *.rc sind absolut identisch (nur ist ein Abschnitt in der einen *.rc ist vertauscht).

Aber deine Version geht und meine nicht.

Wobei: Ich hab mal dein Icon gegen ein anderes ausgetauscht und neu compiliert und trotzdem zeigt er immer noch das alte :freak: Icon an (obwohl im Verzeichnis das icon ein anderes ist)...

Kannst du vielleicht ganz haarklein die Schritt bei der Projekterstellung machen (welche Optionen du gewählt hast etc.).

Crushinator
2003-11-07, 18:08:44
Ich habe das Icon selbstverständlich selbstgemalt. :D Nein im ernst. Ich habe das Gif nur geöffnet CTRL+A, CTRL+C -> umgeswitched in den Ressource-Editor und geCTRL+Vt. Dann habe ich die falschen Farben per Hand nachkorrigiert. Vorher hatte ich ein Strichmännchen im wahrsten Sinne des Wortes gemalt, und damit ging's auch. :ratlos:

Hast Du das Icon im Ressource-Editor gemalt oder in einem anderen Proggi?

/edit: Bei .cpp setzt der Compiler den #define __cplusplus und handelt danach, was hier aber keine Auswirkung hat.

Matrix316
2003-11-07, 18:15:17
Ich hab das Icon im Ressourceneditor "gemalt"...

Weißt du was? Ich schick dir mal meine Version...und dann teste bitte mal aus ob es bei dir geht. WENN es bei der geht, dann ist etwas Faul im Staate Visual C++...:|

Crushinator
2003-11-07, 18:16:40
wo bleibt's? *hetz* :freak: ;)

Matrix316
2003-11-07, 18:17:22
Files sind unterwegs (ca. 17 kb)

Crushinator
2003-11-07, 18:29:11
Fehler gefunden. :laola:

Muddu machen Rechte Maustaste auf "win32uebung4 Dateien" dann "Dateien zu Projekt hinzufügen" -> "icon.rc" auswählen -> OK und das war's. Denn nur dann weiß der Compiler, daß er die .rc auch kompilieren und dazu linken muß. Dein Programm hatte bisher nur kein Icon gefunden, weil ja auch keine Ressourcen in der .Exe drinne waren. =)

Crushinator
2003-11-07, 18:35:24
^^ Damit Dürfte Dein Problem mit dem Überschreiben der .h Datei auch allemal der Vergangenheit angehören. Das nächste mal fügst Du die Ressourcen einfach direkt in der IDE über "Einfügen" -> "Ressource" hinzu und bearbeitest sie auch nur da. (innerhalb der IDE) =)

Matrix316
2003-11-07, 18:44:23
Juhuuuuuuuuuuuuuuuu:invasion:

Aber eigentlich müsste sowas das "Visual Studio" doch selbst machen oder wenigstens FRAGEN ob ich das neue Icon in das Projekt aufnehmen will.

Oder lags daran, dass ich nicht den vorgegebenen Namen sondern einen anderen für das *.rc File benutzt habe?

Unglaublich... :spritz: ;D ZWEI TAGE hin und her wegen SOWAS...:no:

PS.: Vielen dank für die Müh die ich dir gemacht hab. ;)

Crushinator
2003-11-07, 19:11:14
Original geschrieben von Matrix316
Oder lags daran, dass ich nicht den vorgegebenen Namen sondern einen anderen für das *.rc File benutzt habe? Nein, man muß bei solchen komplett selbstgemachten Projekten (ohne Wizzard) immer die .rc manuell hinzufügen, wenn sie nicht schon vorher zum Projekt gehörte. Der Name ist dabei völlig egal. (Hoch lebe MS :bonk: )
PS.: Vielen dank für die Müh die ich dir gemacht hab. ;) No Problem, ich hatte viel Spaß daran. =)

Matrix316
2003-11-07, 19:19:44
Vielleicht kommt ja noch mehr. ;D*eg* :flöt:

Crushinator
2003-11-07, 19:23:15
Wenn ich das - was kommen soll - noch verstehe und ich nebenbei auch noch mein besch....eidenes Termin-Projekt auf der Arbeit gewuppt bekomme, kein Problem. :D

Matrix316
2003-11-07, 19:29:42
Wobei da das jetzt mit den Ressourcen klar ist, ist der Rest eigentlich relativ einfach weil "Schema F". ;)

Aber schaumermal...

Matrix316
2003-11-08, 17:01:29
Ok, eine Frage hab ich doch jetzt noch: Wenn ich einen Cursor selbst zeichne, wie mach ich es, dass der Hintergrund durchsichtig ist und ich kein "Quadrat" durch die Gegend schieb( ;) )?

Crushinator
2003-11-10, 12:29:02
In dem man den Hintergrund im schönen Ko**-Grün vom Ressourcen-Editor beläßt. ;)

Matrix316
2003-11-10, 16:42:34
Asoooooooooooooooo...darauf muss man erstmal kommen...;)

Matrix316
2003-11-12, 15:00:17
Und wieder eine neue Frage. ;D

Ich soll den Titel des Fensters mit "LoadString" angeben, also aus einer Stringtable.

Dafür wurde uns eine Hilfefunktion gegeben die folgendermaßen geht:

LPSTR Load_String(int IdRes)
{
static char buff[255];
if (LoadString(GetModuleHandle(0),IdRes, buff,sizeof(buff)<0))
{
return NULL;
}
else
return (LPSTR)buff;
}

Dann will ich den Wert übergeben z.B.

const char Fenster[255] = Load_String(IDS_STRING1);

Das Problem ist, für die Registrierung von WNDCLASSEX:

wndClass.lpszClassName=Fenster;

Nur leider will der in der WNDCLASSEX für den Namen einen LPCTSTR haben, aber ich bekomm mit Load_String nur einen LPSTR...und konvertieren geht auch nicht...

~\win32.cpp(15) : error C2440: 'initializing' : 'char *' kann nicht in 'const char [255]' konvertiert werden

KANN ich überhaupt den "lpszClassName" mit Load String laden?

Matrix316
2003-11-12, 16:17:31
Ok, Problem hat sich erledigt. :)

Matrix316
2003-11-12, 16:59:05
Na toll, also ich hab eine Stringtable mit diversen Texten und die werden auch an bestimmten Stellen im Programm richtig aufgerufen, nur schreibt der ÜBERALL den gleichen Text des letzten erstellten Eintrages in der Stringtable hin!!!

In dieser stehts so:


STRINGTABLE DISCARDABLE
BEGIN
IDS_STRING1 "Das ist ein Fenster"
IDS_STRING2 "Klasse nicht Registriert"
IDS_STRING3 "Fenster wurde gemacht von mir."
IDS_STRING4 "Info Dialog"
END

#endif


Programmcode:


#include <windows.h>
#include "resource.h"

const char *Fenster = "WinFenster";


LPCTSTR Load_String(unsigned int IDName)
{
static char buffer[255];
if (LoadString(GetModuleHandle(0),IDName,buffer,sizeof(buffer))<0)
{
return NULL;
}
else
return (LPCTSTR)buffer;
}

LRESULT CALLBACK WndProcedure(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
const char *text=Load_String(IDS_STRING3);
const char *text1=Load_String(IDS_STRING4);


switch(iMsg)
{
case WM_COMMAND:
switch (LOWORD(wParam))
{
case ID_DATEI_BEENDEN:
DestroyWindow(hWnd);
break;
case ID_FENSTER_BILDSCHIRMLSCHEN:
break;
case ID_FENSTER_LIENIENFARBENDERN:
break;
case ID__INFO:
MessageBox(hWnd, text , text1,0);
break;
}

case WM_PAINT:
hDC=BeginPaint(hWnd,&ps);
TextOut(hDC,10,30,text,strlen(text));
EndPaint(hWnd,&ps);
break;
case WM_CLOSE:
//GetWindowMenuPopup(ID_DATEI_BEENDEN);
DestroyWindow(hWnd);
break;

case WM_DESTROY:
PostQuitMessage(0);
break;
}

return DefWindowProc(hWnd, iMsg, wParam, lParam);
}

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCms)
{
WNDCLASSEX wndClass;
HWND hWnd;
MSG Msg;

wndClass.cbSize=sizeof(WNDCLASSEX);
wndClass.style=CS_HREDRAW|CS_VREDRAW;
wndClass.lpfnWndProc=WndProcedure;
wndClass.cbClsExtra=0;
wndClass.cbWndExtra=0;
wndClass.hInstance=hInstance;

wndClass.hIcon=LoadIcon(GetModuleHandle(NULL),MAKEINTRESOURCE(IDI_ICON1));
wndClass.hIconSm=(HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON1),
IMAGE_ICON, 16, 16, 0);
wndClass.hCursor = LoadCursor(hInstance,MAKEINTRESOURCE(IDC_CURSOR1));
wndClass.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
wndClass.lpszMenuName=MAKEINTRESOURCE(IDR_MENU1);
wndClass.lpszClassName=Fenster;

if (!RegisterClassEx(&wndClass))
{
MessageBox(NULL,Load_String(IDS_STRING2), 0,0);
return -1;
}

hWnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
Fenster,
Load_String(IDS_STRING1),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
640,
480,
NULL,
NULL,
hInstance,
NULL);

if(hWnd == NULL)
{
MessageBox(NULL, "Window Creation Failed!", "Error!",0);
return 0;
}

ShowWindow(hWnd, nShowCms);
UpdateWindow(hWnd);




while(GetMessage(&Msg, NULL, 0, 0))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}

return 0;

}


Und hier das resultat:

Matrix316
2003-11-12, 18:26:21
Wie mach ich es eigentlich, dass ich mit Mausklicks zeichnen kann?

Mit WM_LBUTTONDOWN oder so bekommt ich die Position des Mauszeigers.


case WM_LBUTTONDOWN:
posm.xPos = LOWORD(lParam);
posm.yPos = HIWORD(lParam);


und mit


MoveToEx(hDC, posm.xPos, posm.yPos, NULL);
LineTo(hDC, posm.xPos, posm.yPos);


Kann ich eine Linie Zeichnen. Nur irgendwie reagiert er nicht auf die Mausklicks, bzw wie kann man dem "LineTo klar machen, wo es hin soll? :bonk: (ja ich weiß, hört sich strange an)

Crushinator
2003-11-13, 16:49:54
Uuuups. Mir ist augefallen, daß Du in "Load_String" immer einen und denselben "static char buffer[255]" füllst. Jetzt rate mal was passiert, wenn InfoText und InfoText1 (sind ja auch nur Zeiger) auf die selbe Adresse zeigen. Ja, genau: Es wird immer nur das genommen, was als Letztes in buffer geladen wurde. :D

Jetzt mal auf ganz doof:

LPCSTR Load_String(unsigned int IDName)
{
static char buffer[255];
if (LoadString(GetModuleHandle(NULL),IDName,buffer,sizeof(buffer))<0)
{
return "";
}
else
return (LPCSTR)buffer;
}

...

char text[255];
char text1[255];

/*
const char *text=Load_String(IDS_STRING3);
const char *text1=Load_String(IDS_STRING4);
/*

strcpy(text, Load_String(IDS_STRING3));
strcpy(text1, Load_String(IDS_STRING4));

Dann klappt's auch mit der MessageBox.

Crushinator
2003-11-13, 17:02:16
Original geschrieben von Matrix316
(...) Nur irgendwie reagiert er nicht auf die Mausklicks, bzw wie kann man dem "LineTo klar machen, wo es hin soll? :bonk: (ja ich weiß, hört sich strange an) Mit "MoveToEx" gibt man die Anfangsposition an und mit LineTo die Endposition. Hilfreich ist's wenn sie sich dabei unterscheiden. ;) "BeginPaint" und "EndPaint" sollten auch nicht vergessen werden.

Matrix316
2003-11-13, 17:19:39
Ist ja schon alles berücksichtigt worden...

Ok ich hab jetzt im Programm (dank eines Tutorials) dass ich freihändig zeichnen kann.


#include <windows.h>
#include <stdio.h>
#include "stringtext.h"
#include "resource.h"


const char *Fenster = "WinFenster";


LPCTSTR Load_String(unsigned int IDName);
BOOL CALLBACK DialogProc(HWND hDlg,UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK WndProcedure(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCms)
{
WNDCLASSEX wndClass;
HWND hWnd;
MSG Msg;

wndClass.cbSize=sizeof(WNDCLASSEX);
wndClass.style=CS_HREDRAW|CS_VREDRAW;
wndClass.lpfnWndProc=WndProcedure;
wndClass.cbClsExtra=0;
wndClass.cbWndExtra=0;
wndClass.hInstance=hInstance;

wndClass.hIcon=LoadIcon(GetModuleHandle(NULL),MAKEINTRESOURCE(IDI_ICON1));
wndClass.hIconSm=(HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON1),
IMAGE_ICON, 16, 16, 0);
wndClass.hCursor = LoadCursor(hInstance,MAKEINTRESOURCE(IDC_CURSOR1));
wndClass.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
wndClass.lpszMenuName=MAKEINTRESOURCE(IDR_MENU1);
wndClass.lpszClassName=Fenster;

if (!RegisterClassEx(&wndClass))
{
MessageBox(NULL,Fehler, 0,0);
return -1;
}

hWnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
Fenster,
Titel,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
640,
480,
NULL,
NULL,
hInstance,
NULL);

if(hWnd == NULL)
{
MessageBox(NULL, "Window Creation Failed!", "Error!",0);
return 0;
}

ShowWindow(hWnd, nShowCms);
UpdateWindow(hWnd);

while(GetMessage(&Msg, NULL, 0, 0))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}

return 0;

}

LPCTSTR Load_String(unsigned int IDName)
{
static char buffer[255];
if (LoadString(GetModuleHandle(0),IDName,buffer,sizeof(buffer))<0)
{
return NULL;
}
else
return (LPCTSTR)buffer;
}


BOOL CALLBACK DialogProc(HWND hDlg,UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_INITDIALOG:

return TRUE;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDOK:
EndDialog(hDlg, IDOK);
break;
case IDCANCEL:
EndDialog(hDlg, IDCANCEL);
break;
}
break;
default:
return FALSE;
}
return TRUE;

}

LRESULT CALLBACK WndProcedure(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
static char PosText[128];
static int xPos1=-1, yPos1=-1, xPos2=-1, yPos2=-1;
//int rot, gruen, blau;
HPEN stift = CreatePen( PS_SOLID, 4, RGB(255, 0, 255 ));

switch(iMsg)
{
case WM_COMMAND:
switch (LOWORD(wParam))
{
case ID_DATEI_BEENDEN:
DestroyWindow(hWnd);
break;
case ID_FENSTER_BILDSCHIRMLSCHEN:
xPos1=xPos2=yPos1=yPos2=-1;
InvalidateRect(hWnd, NULL, TRUE);
break;
case ID_FENSTER_LINIENFARBENDERN_ROT:

break;
case ID_FENSTER_LINIENFARBENDERN_GRUEN:

break;
case ID_FENSTER_LINIENFARBENDERN_BLAU:

break;
case ID_FENSTER_LINIENFARBENDERN_SCHWARZ:

break;
case ID_FENSTER_LINIENFARBENDERN_GELB:

break;
case ID__INFO:

int ret = DialogBox(GetModuleHandle(NULL),MAKEINTRESOURCE(IDD_DIALOG1), hWnd, DialogProc);

if(ret == -1)
{
MessageBox(hWnd, "Dialog failed!", "Fehler",MB_OK | MB_ICONINFORMATION);
}

break;
}

case WM_LBUTTONDOWN:
xPos1 = LOWORD(lParam);
yPos1 = HIWORD(lParam);
hDC = GetDC( hWnd );
sprintf( PosText,
"Linke Maustaste an Pos.: X = %04d, Y = %04d",xPos1,yPos1);
TextOut( hDC, 10, 60, PosText, lstrlen( PosText ) );
ReleaseDC( hWnd, hDC );
break;

case WM_PAINT:

hDC=BeginPaint(hWnd,&ps);

SelectObject(hDC, stift);
MoveToEx(hDC, xPos1, yPos1, NULL);
LineTo(hDC, xPos2, yPos2);
DeleteObject(stift);

EndPaint(hWnd,&ps);
break;

case WM_MOUSEMOVE:
xPos1=xPos2; //für MoveToEx
yPos1=yPos2; //für MoveToEx
xPos2=LOWORD(lParam); //neue x-Position
yPos2=HIWORD(lParam); //neue y-Postion
//nur Zeichnen, wenn linker Button gedrückt ist
if(wParam & MK_LBUTTON)
{
InvalidateRect(hWnd,NULL,FALSE);
}
return 0;
//rechte Maustaste->Bildschirm löschen

/*case WM_RBUTTONDOWN:
xPos1=xPos2=yPos1=yPos2=-1;
InvalidateRect(hWnd, NULL, TRUE);
break;*/


case WM_CLOSE:
DestroyWindow(hWnd);
break;

case WM_DESTROY:
PostQuitMessage(0);
break;
}

return DefWindowProc(hWnd, iMsg, wParam, lParam);
}


Das Problem ist, ich will garnicht freihändig zeichnen, sondern der soll immer eine gerade Linie von Mausklick zu Mausklick zeichen.

Auch noch ein Problem ist die Linienfarbe. Wenn ich für die drei zahlen beim "Stift" jeweils eine Variable nehme und beim Menüeintrag Linienfarbe ändern rot, gruen etc. diese Werte ändern, ändert sich NICHT die Stiftfarbe, sondern die bleibt immer gleich...(ist im Moment nicht eingebaut!)

Crushinator
2003-11-13, 17:35:00
^^ Muß kurz weg, in 2 Std. komm' ich wieder.

Matrix316
2003-11-13, 17:46:40
Alles klar.

Ok, ich habs jetzt soweit, das er die Linie nacheinander Zeichnet, aber er beginnt nicht da wo ich hinklicke, sondern immer links oben!


LRESULT CALLBACK WndProcedure(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
static char PosText[128];
static int xPos1, yPos1, xPos2, yPos2;
//int rot, gruen, blau;
HPEN stift = CreatePen( PS_SOLID, 4, RGB(255, 0, 255 ));

switch(iMsg)
{
case WM_COMMAND:
switch (LOWORD(wParam))
{
case ID_DATEI_BEENDEN:
DestroyWindow(hWnd);
break;
case ID_FENSTER_BILDSCHIRMLSCHEN:
xPos1=xPos2=yPos1=yPos2=-1;
InvalidateRect(hWnd, NULL, TRUE);
break;
case ID_FENSTER_LINIENFARBENDERN_ROT:

break;
case ID_FENSTER_LINIENFARBENDERN_GRUEN:

break;
case ID_FENSTER_LINIENFARBENDERN_BLAU:

break;
case ID_FENSTER_LINIENFARBENDERN_SCHWARZ:

break;
case ID_FENSTER_LINIENFARBENDERN_GELB:

break;
case ID__INFO:

int ret = DialogBox(GetModuleHandle(NULL),MAKEINTRESOURCE(IDD_DIALOG1), hWnd, DialogProc);

if(ret == -1)
{
MessageBox(hWnd, "Dialog failed!", "Fehler",MB_OK | MB_ICONINFORMATION);
}

break;
}

case WM_LBUTTONDOWN:

xPos2=xPos1; //für MoveToEx
yPos2=yPos1; //für MoveToEx

xPos1=LOWORD(lParam); //neue x-Position
yPos1=HIWORD(lParam); //neue y-Postion

InvalidateRect(hWnd,NULL,FALSE);

hDC = GetDC( hWnd );
sprintf( PosText,
"Linke Maustaste an Pos.: X = %04d, Y = %04d",xPos1,yPos1);
TextOut( hDC, 10, 60, PosText, lstrlen( PosText ) );
ReleaseDC( hWnd, hDC );
break;

case WM_PAINT:

hDC=BeginPaint(hWnd,&ps);

SelectObject(hDC, stift);
MoveToEx(hDC, xPos1, yPos1, NULL);
LineTo(hDC, xPos2, yPos2);
DeleteObject(stift);

EndPaint(hWnd,&ps);
break;

[...]

MeLLe
2003-11-13, 18:16:22
Wie wäre da ...

xPos1=xPos2; //für MoveToEx
xPos1=yPos2; //für MoveToEx

xPos2=LOWORD(lParam); //neue x-Position
yPos2=HIWORD(lParam); //neue y-Postion

... ? ;)

Matrix316
2003-11-13, 18:41:39
Naja, im Moment machts sowas:

Crushinator
2003-11-13, 19:44:23
Hoffe, das macht genau das, was Du Dir vorgestellt hast.


case WM_LBUTTONDOWN:
xPos1 = LOWORD(lParam);
yPos1 = HIWORD(lParam);
hDC = GetDC( hWnd );
sprintf( PosText,
"Linke Maustaste an Pos.: X = %04d, Y = %04d",xPos1,yPos1);
TextOut( hDC, 10, 60, PosText, lstrlen( PosText ) );
ReleaseDC( hWnd, hDC );
break;

case WM_LBUTTONUP: /* <- :wink: */
xPos1=xPos2; //für MoveToEx
yPos1=yPos2; //für MoveToEx
xPos2=LOWORD(lParam); //neue x-Position
yPos2=HIWORD(lParam); //neue y-Postion
if (xPos1 > 0 && yPos1 > 0)
InvalidateRect(hWnd,NULL,FALSE);
break;

/* Wech damit
case WM_MOUSEMOVE:
...
break;
*/

Matrix316
2003-11-13, 20:17:28
:massa:

WM_LBUTTONUP :bonk: da hätt man auch selbst draufkommen können...;)

JUHU, es geht. :)

Aber eine Sache hab ich noch, einen hab ich noch, einhabichnoch ;):

Die Farbe der Linien:

Ich hab das mal so probiert, aber es bleibt immer die, welche am Anfang eingestellt ist:


LRESULT CALLBACK WndProcedure(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
static char PosText[128];
static int xPos1, yPos1, xPos2, yPos2;
int rot=255, gruen=125, blau=0;
HPEN stift = CreatePen( PS_SOLID, 4, RGB(rot,gruen,blau));

switch(iMsg)
{
case WM_COMMAND:
switch (LOWORD(wParam))
{
case ID_DATEI_BEENDEN:
DestroyWindow(hWnd);
break;
case ID_FENSTER_BILDSCHIRMLSCHEN:
xPos1=xPos2=yPos1=yPos2=-1;
InvalidateRect(hWnd, NULL, TRUE);
break;
case ID_FENSTER_LINIENFARBENDERN_ROT:
rot=255;
gruen=0;
blau=0;
break;
case ID_FENSTER_LINIENFARBENDERN_GRUEN:
rot=0;
gruen=255;
blau=0;
break;
case ID_FENSTER_LINIENFARBENDERN_BLAU:
rot=0;
gruen=0;
blau=255;
break;
case ID_FENSTER_LINIENFARBENDERN_SCHWARZ:
rot=0;
gruen=0;
blau=0;
break;
case ID_FENSTER_LINIENFARBENDERN_GELB:
rot=255;
gruen=255;
blau=0;
break;


EDIT: Ich hab jetzt die rot, gruen etc. Variablen global gemacht, und jetzt ändert er die Farben. Gibts eigentlich auch eine Möglichkeit, dass die schon vorhandenen Linien eine andere Farbe bekommen können?

Crushinator
2003-11-13, 20:36:48
Original geschrieben von Matrix316
(...) Ich hab jetzt die rot, gruen etc. Variablen global gemacht, und jetzt ändert er die Farben. Gibts eigentlich auch eine Möglichkeit, dass die schon vorhandenen Linien eine andere Farbe bekommen können? Nein, leider muß man sie nochmal "nachmalen". ;(

Matrix316
2003-11-13, 20:38:58
Hmmm...naja egal.

Gibts eigentlich noch eine andere Möglichkeit die Schriftart zu ändern außer mit:

font = CreateFont(46, etc. etc...................);

Crushinator
2003-11-13, 20:56:29
^^ Leider auch nicht (http://www.winprog.org/tutorial/fonts.html).

Matrix316
2003-11-13, 21:21:41
Das wird ja immer besser. ;D

Ok, nächste Frage: In der Aufgabenstellung steht:

Der Info Dialog soll weiterhin durch die Tastenkombination ALT-? (also ALT-Shift-?) angezeigt werden. [Acceleratortable verwenden]

Was ist damit genau gemeint? Soll sich das Fenster direkt öffnen oder wird nur das Menü aktiviert oder wie oder was?

Oder ist damit gemeint, dass im Menü der erste Buchstabe unterstrichen ist und man so mit alt+zeichen dieses anwählen kann?

Crushinator
2003-11-13, 22:46:21
Das soll heißen, daß Du einen Extra-Shortcut für das Aufrufen des Info-Dialogs brauchst. Auf Ressourcen->Einfügen->Accelerator->Neu und da ist der Accelerator. Dann ist es ähnlich wie bei den Strings, wie man sie anlegt. ID vergeben, Tastenkürzel, Rest nicht anfassen, fertig. Einbinden tut man das Ganze mit "LoadAccelerators".

Mehr erzähle ich jetzt nicht, denn Du sollst erstmal genau so leiden wie ich es damals tat und dabei was lernen. :D Bei genügend sichtbaren Bemühungen werden einzelne Fragen dennoch beantwortet. ;)

Matrix316
2003-11-13, 23:19:42
Hm, ich hab son Ding gemacht und:

LoadAccelerators(hInstance,MAKEINTRESOURCE(IDR_ACCELERATOR1));

jetzt im winmain drin stehen.

Aber wenn ich im Programm alt+shift+? drücke wird das Menü unter dem ? markiert und geöffnet - aber das war vorher auch schon so... (weil im Menü ein & vor dem ? steht)

Oder kommt das LoadAcceleratos in die Callback Funktion? :kratz:

So siehts jetzt und sahs auch vorher aus bei alt+shift+?

Crushinator
2003-11-13, 23:30:40
Original geschrieben von Matrix316
LoadAccelerators(hInstance,MAKEINTRESOURCE(IDR_ACCELERATOR1)); Ich hoffe, Du hast das Ergebnis dieser Func auch einer Variable zugewiesen, denn man braucht sie später. In der WinMain ist sie aber schonmal richtig. Hassu denn nix an Beispielen im Netz gefunden?
(...) (weil im Menü ein & vor dem ? steht) Das auch. :D

Matrix316
2003-11-14, 10:06:51
1. Bei google bekommt man gerade so eine Seite, allerdings jetzt wo du es sagst, hab ich was gefunden. ;)

2. Was meinste jetzt damit? Ist so ein selbst gemachter Dinges praktisch identisch mit dem & vor einem Buchstaben???

Matrix316
2003-11-14, 11:08:40
Also ich hab jetzt mal die "Musterlösung" gesehen. Und da ändert sich auch die Farbe der Linie die schon gezeichnet wurde.

PS.: Wie kann ich eigentlich Text löschen den ich mit TextOut ausgegeben habe?

Crushinator
2003-11-14, 11:31:33
Original geschrieben von Matrix316
2. Was meinste jetzt damit? Ist so ein selbst gemachter Dinges praktisch identisch mit dem & vor einem Buchstaben??? Nicht ganz, denn bei dem "selbstgemachten" Ding geht gleich das Dialog auf anstatt, daß nur das Menü aufgeklappt wird.

Und zur Musterlösung: Da wird wohl entweder die der ganze Foreground im Speicher gecached :freak: oder sich die Linien-Positionen in einem Array zum nachmalen gebookmarked. Es kann natürlich auch sein, daß ich mich damit auf dem Holzweg befinde und es gibt diese ominöse Möglichkeit wirklich, nur habe ich bisher nicht viel mit den GDI-Linien machen müssen, um mir dessen 100%ig sicher zu sein. Ich werd' mich jedenfalls heute (spät) Nachmittag mal auf die Suche nach einer ggf. vorhandenen Möglichkeit begeben.

/edit: TextOut -> ähnlich wie die Linien. (Nochmal mit Backgroundfarbe drüber schreiben) :freak:

Matrix316
2003-11-14, 12:06:17
Und wie ändere ich die Farbe vom TextOut?

(EDIT: Ok, rausgefunden: mit SetTextColor(hdc, RGB(255,255,255)); nur sieht man jetzt überall Lücken wo vorher Text war ;) )

Da gibts ja nur den Handle, xpos, ypos, den Text und die Länge als Optionen, oder muss ich für den ganzen spaß DrawText nehmen?

Aber es MUSS doch irgendwie was geben wie z.B. RemoveText(...) oder sowas. ;)

Was mir noch auffällt, wenn ich die Lösung "minimiere" und wieder aufrufe, sind die Linien noch da. Bei mir sind sie weg...:(

PS.: An so einen Array hab ich auch schon gedacht wo man die vorherigen Positionen der Maus speichert. Die Frage ist nur wie groß der sein müsste. =)

Gibts keine Funktion die den Bildschirminhalt mit aktuellen Parametern neu zeichnet, ohne was zu löschen?

Matrix316
2003-11-14, 13:26:14
Hmmmm, ich hab jetzt die Funktion "RedrawWindow" gefunden, aber irgendwie hab ich keinen Plan was die meisten Parameter bedeuten sollen...


BOOL RedrawWindow(
HWND hWnd, // handle of window (<<<OK, das ist klar ;))
CONST RECT *lprcUpdate,
// address of structure with update rectangle
HRGN hrgnUpdate, // handle of update region
UINT flags // array of redraw flags
);

Gast
2003-11-14, 14:51:17
kuck dir mal die tutorials hier an:

http://www.luckie-online.de/tutorials/win32apituts/

die sind zwar für delphi geschrieben, sollten aber leicht nach c++ umgesetzt werden können.

Matrix316
2003-11-14, 16:31:20
Kenn ich schon, aber trotzdem thx.

Das Problem bei den ganzen Tutorials ist, die zeigen wie mans MACHT aber wie es rückgängig gemacht wird steht meistens nirgends...

Xmas
2003-11-14, 17:23:13
Dazu wirst du auch kein Tutorial finden können, weil es schlicht keine Funktion gibt die das Malen rückgängig macht.

Du kannst aber alle Linien mit Start- und Endkoordinaten speichern, und dann bei jedem Redraw neu zeichnen.

Matrix316
2003-11-14, 17:48:13
Original geschrieben von Xmas
Dazu wirst du auch kein Tutorial finden können, weil es schlicht keine Funktion gibt die das Malen rückgängig macht.

Du kannst aber alle Linien mit Start- und Endkoordinaten speichern, und dann bei jedem Redraw neu zeichnen.

Aber, dann stürzt es irgendwann ab, weil man ja nicht unendliche Koordinaten speichern kann, oder?

Gibts keine Funktion, die den Bildschirm refreshed sozusagen?

Crushinator
2003-11-14, 19:01:21
Original geschrieben von Xmas
(...)
Du kannst aber alle Linien mit Start- und Endkoordinaten speichern, und dann bei jedem Redraw neu zeichnen. Genau das. Ich habe nun auch alles, was ich an Büchern habe und was im Netz zu finden möglich war durch und bin bisher zu diesem Ergebnis gekommen:

Array oder noch besser Objekte (evtl. in einem Collector) anlegen, darin Farbe, Begin- und Endpoints merken und bei WM_PAINT jedes Element erneut zeichnen. So werden übrigens auch ganze Controls "gezeichnet" (http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/dnarvc/html/msdn_custctl.asp). "Malen Rückgängig machen" verhält sich genau so, laut Micros~1 nämlich in dieser (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/fillshap_7m7n.asp) Art und mit anderen Worten: Drüber malen. :D


// If a previous target rectangle exists, erase
// it by drawing another rectangle on top.

if (!IsRectEmpty(&rcTarget))
{
Rectangle(hdc, rcTarget.left, rcTarget.top,
rcTarget.right, rcTarget.bottom);
}

Redraw geht übrigens auch so (http://www.geocities.com/Heartland/Meadows/9818/win32tut/gdi.html) wie ich vorhin erwähnt hatte:
If you minimize the window and restore it, you’ll notice that everything you’ve drawn is erased. This is because Windows sends the WM_PAINT message to your application telling it to redraw its client area. To keep persistent drawings, you’ve got two options – to keep a list of all objects and draw them on every call to WM_PAINT or to keep a snapshot of the image and redraw it on WM_PAINT.
Gerade aufbauend hört sich das aber wahrscheinlich nicht an, oder? X-D

Matrix316
2003-11-14, 19:14:42
:kratz2: :grübel: :kratz: :greydead:

Was heißt hier eigentlich "Rectangle" - Rechteck??? Oder gibts noch eine allgemeinere Bedeutung?

Ui, die Hammer Idee: Es müsste doch gehen einen Array aus Structs zu machen oder so.

Also einen Eindimensionalen Array, wo jedes Zeichen ein Struct ist bestehend aus Farbe, Anfang und Ende speichere oder so. ;)

Crushinator
2003-11-14, 19:17:36
Original geschrieben von Matrix316
(...) Aber es MUSS doch irgendwie was geben wie z.B. RemoveText(...) oder sowas. ;) Gibt's auch, nennt sich ...

hdc = GetDC(hwnd);
SetROP2(hdc, R2_NOTXORPEN );
Rectangle(hdc, TextAnfang.x, TextAnfang.y, TextEnde.x, TextEnde.y )
ReleaseDC(hwnd, hdc);

Rectangle == Rechtwinkel ...ähhmmm... Rechteck. X-D

/edit: In meinem vorigen Posting wird ein zuvor gemaltes Rechteck mit dem Code "rückgangig" gemacht.

Matrix316
2003-11-14, 19:23:34
Original geschrieben von crushinator
Gibt's auch, nennt sich ...

hdc = GetDC(hwnd);
SetROP2(hdc, R2_NOTXORPEN );
Rectangle(hdc, TextAnfang.x, TextAnfang.y, TextEnde.x, TextEnde.y )
ReleaseDC(hwnd, hdc);

Rectangle == Rechtwinkel ...ähhmmm... Rechteck. X-D

/edit: In meinem vorigen Posting wird ein zuvor gemaltes Rechteck mit dem Code "rückgangig" gemacht.

Das heißt es wird einfach ein weißes Rechteck drüber geplackt? :bonk:

Also ich habs jetzt, dass der Text nur am Ende steht und zwar wie schon gesagt überschreib ich den alten Text mit weißer Schrift. ;)


case WM_LBUTTONDOWN:
hDC = GetDC( hWnd );
SetTextColor(hDC, RGB(255,255,255));
sprintf( PosText,MousePosition,xPos1,yPos1);
TextOut( hDC, xPosAlt, yPosAlt, PosText, lstrlen( PosText) );
ReleaseDC( hWnd, hDC );
[...]
xPosAlt=xPos1;
yPosAlt=yPos1;

Matrix316
2003-11-14, 19:27:06
Nur siehts jetzt so aus:

Crushinator
2003-11-14, 19:46:06
Dann solltest Du das mit dem Array versuchen und nach dem Löschen des Textes die Linien "nachmalen", allerdings bevor Du den neuen Text schreibst. :)

Matrix316
2003-11-14, 20:02:25
Hmmmm...

Geht das Malen der Linie auch außerhalb des WM_PAINT Abschnitts bzw. außerhalb der BeginPaint und End Paint?

Wann wird eigentlich WM_PAINT ausgeführt?

Crushinator
2003-11-14, 20:33:06
Original geschrieben von Matrix316
Geht das Malen der Linie auch außerhalb des WM_PAINT Abschnitts bzw. außerhalb der BeginPaint und End Paint? Klar, geht das. Nur muß es auch in WM_PAINT passieren, weil das Fenster sonst leer wäre wenn es minimiert oder von was anderem verdeckt wurde und dann wieder sichtbar ist.
WM_PAINT wird gesendet, wenn ein Neuzeichnen des Fensters notwendig wird, z.B. wenn ein Teil des Dialogfensters für ungültig erklärt wird (nach Überdecken durch ein anderes Window, Verschieben über den Bildschirmrand, Minimieren etc.).

Matrix316
2003-11-14, 20:39:41
Achso achso achsooooo....

Hmmm...

Ich hab jetzt vor eine Funktion zu machen, die mir einfach das Bild neuzeichnet bis zum aktuellen Punkt. Nur hab ich ein Problem, und zwar hab ich erstmal einen Struct gemacht:

struct sRepaintDaten{int rot; int gruen; int blau; int xPos1; int yPos1; int xPos2; int yPos2;};

dann einen Array

struct sRepaintDaten RepDat[];

Dann eine Funktion:

void Repaint(HWND hWnd, HDC hDC)
{
PAINTSTRUCT ps;
for (i=0; i<sizeof(RepDat); i++)
{
HPEN stift = CreatePen( PS_SOLID, 5, RGB(RepDat[i].rot,RepDat[i].gruen,RepDat[i].blau));
hDC=BeginPaint(hWnd,&ps);
SelectObject(hDC, stift);
MoveToEx(hDC, RepDat[i].xPos1, RepDat[i].yPos1, NULL);
LineTo(hDC, RepDat[i].xPos2, RepDat[i].yPos2);
DeleteObject(stift);
EndPaint(hWnd,&ps);
}
}

Problem ist, bei dem sizeof in der Forschleife gibts eine Fehlermeldung:

F:\Schnittstellen0304\Uebung4\win32uebung4\win32.cpp(254) : error C2070: ungueltiger sizeof-Operand


sizeof(RepDat[]) geht aber auch nicht.

Crushinator
2003-11-14, 21:20:29
:???:

struct sRepaintDaten{int rot; int gruen; int blau; int xPos1; int yPos1; int xPos2; int yPos2;};
struct sRepaintDaten RepDat[] = {0,0,0,0,0,0,0};

for (i=0; i<sizeof(RepDat); i++)
Sleep(1);

Kompiliere, kompiliere, trinke dabei viele Biere
...
MyPrj.exe - 0 Fehler, 0 Warnung(en) :ratlos:

Außerdem sollte es IMHO lieber so aussehen:

for (i=0; i<sizeof(RepDat) / sizeof(struct sRepaintDaten); i++)
:)

Matrix316
2003-11-14, 21:47:32
Ich brauch ja die Anzahl der Array Mitglieder. Der Struct ist ja egal wie groß der ist. ;)

EDIT: Ich hab jetzt die Repaint Funktion in WM_LBUTTONUP, DOWN und WM_PAINT drinstehen, aber es passiert rein garnichts...

gefüllt hab ich den array so:


case WM_LBUTTONUP:

RepDat[i].xPos1=xPos1;
RepDat[i].yPos1=yPos1;

xPos1=xPos2;
yPos1=yPos2;
xPos2=LOWORD(lParam);
yPos2=HIWORD(lParam);

RepDat[i].xPos2=xPos2;
RepDat[i].yPos2=xPos2;

i++;

Repaint(hWnd,hDC);

if (xPos1 > 0 && yPos1 > 0)

InvalidateRect(hWnd,NULL,FALSE);
break;

Crushinator
2003-11-14, 22:02:08
Original geschrieben von Matrix316
Ich brauch ja die Anzahl der Array Mitglieder. Der Struct ist ja egal wie groß der ist. ;) (...) Und wie hoch ist die Anzahl? Hast Du schon einen iCount = sizeof(RepDat); gemacht und geschaut, was bei 3 Array-Members dann in iCount steht? :naughty:

P.S.: mal Repaint(..) direkt vor break; versucht?

Matrix316
2003-11-14, 22:53:16
Also vor Break macht er was, aber nicht was er soll...

Bei dem iCount steht jedesmal: 124896 oder sowas ;)

Ok, das könnte sein, weil RepDat an sich ja ein Zeiger auf die Adresse der ersten Stelle des Arrays ...

Ok, hier nochmal der ganze Code:


#include <windows.h>
#include <stdio.h>
#include "stringtext.h"
#include "resource.h"


const char *Fenster = "WinFenster";
int rot=255, gruen=125, blau=0;
int i,j,k,l;
int iCount;

struct sRepaintDaten{int rot; int gruen; int blau; int xPos1; int yPos1; int xPos2; int yPos2;};
struct sRepaintDaten RepDat[] = {0,0,0,0,0,0,0};
/*Zugrff auf Inhalt des Structs
RepDat[i].xPos1
RepDat[i].xPos2
RepDat[i].yPos1
RepDat[i].yPos2
RepDat[i].rot
RepDat[i].gruen
RepDat[i].blau*/
LPCTSTR Load_String(unsigned int IDName);
BOOL CALLBACK DialogProc(HWND hDlg,UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK WndProcedure(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam);

void Repaint(HWND hWnd, HDC hDC);




int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCms)
{
WNDCLASSEX wndClass;
HWND hWnd;
MSG Msg;
HACCEL hAcl;

wndClass.cbSize=sizeof(WNDCLASSEX);
wndClass.style=CS_HREDRAW|CS_VREDRAW;
wndClass.lpfnWndProc=WndProcedure;
wndClass.cbClsExtra=0;
wndClass.cbWndExtra=0;
wndClass.hInstance=hInstance;

wndClass.hIcon=LoadIcon(GetModuleHandle(NULL),MAKEINTRESOURCE(IDI_ICON1));
wndClass.hIconSm=(HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON1),
IMAGE_ICON, 16, 16, 0);
wndClass.hCursor = LoadCursor(hInstance,MAKEINTRESOURCE(IDC_CURSOR1));
wndClass.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
wndClass.lpszMenuName=MAKEINTRESOURCE(IDR_MENU1);
wndClass.lpszClassName=Fenster;

if (!RegisterClassEx(&wndClass))
{
MessageBox(NULL,Fehler, 0,0);
return -1;
}

hWnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
Fenster,
Titel,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
640,
480,
NULL,
NULL,
hInstance,
NULL);

if(hWnd == NULL)
{
MessageBox(NULL, "Window Creation Failed!", "Error!",0);
return 0;
}

hAcl=LoadAccelerators(hInstance,MAKEINTRESOURCE(IDR_ACCELERATOR1));

ShowWindow(hWnd, nShowCms);
UpdateWindow(hWnd);




while(GetMessage(&Msg, NULL, 0, 0))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}

return 0;

}

LPCTSTR Load_String(unsigned int IDName)
{
static char buffer[255];
if (LoadString(GetModuleHandle(0),IDName,buffer,sizeof(buffer))<0)
{
return NULL;
}
else
return (LPCTSTR)buffer;
}


BOOL CALLBACK DialogProc(HWND hDlg,UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_INITDIALOG:

return TRUE;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDOK:
EndDialog(hDlg, IDOK);
break;
case IDCANCEL:
EndDialog(hDlg, IDCANCEL);
break;
}
break;
default:
return FALSE;
}
return TRUE;

}

LRESULT CALLBACK WndProcedure(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
static char PosText[128];
static int xPos1, yPos1, xPos2, yPos2;
HPEN stift = CreatePen( PS_SOLID, 5, RGB(rot,gruen,blau));

static int xPosAlt, yPosAlt;

switch(iMsg)
{
case WM_COMMAND:
switch (LOWORD(wParam))
{
case ID_DATEI_BEENDEN:
DestroyWindow(hWnd);
break;
case ID_FENSTER_BILDSCHIRMLSCHEN:
xPos1=xPos2=yPos1=yPos2=-1;
InvalidateRect(hWnd, NULL, TRUE);
break;
case ID_FENSTER_LINIENFARBENDERN_ROT:

rot=255;
gruen=0;
blau=0;
break;
case ID_FENSTER_LINIENFARBENDERN_GRUEN:
rot=0;
gruen=255;
blau=0;

break;
case ID_FENSTER_LINIENFARBENDERN_BLAU:
rot=0;
gruen=0;
blau=255;

break;
case ID_FENSTER_LINIENFARBENDERN_SCHWARZ:
rot=0;
gruen=0;
blau=0;

break;
case ID_FENSTER_LINIENFARBENDERN_GELB:
rot=255;
gruen=255;
blau=0;

break;
case ID__INFO:

int ret = DialogBox(GetModuleHandle(NULL),MAKEINTRESOURCE(IDD_DIALOG1), hWnd, DialogProc);

if(ret == -1)
{
MessageBox(hWnd, "Dialog failed!", "Fehler",MB_OK | MB_ICONINFORMATION);
}

break;
}

case WM_LBUTTONDOWN:
//TextLöschen!
hDC = GetDC( hWnd );
SetTextColor(hDC, RGB(255,255,255));
sprintf( PosText,MousePosition,xPos1,yPos1,iCount);
TextOut( hDC, xPosAlt, yPosAlt, PosText, lstrlen( PosText) );
ReleaseDC( hWnd, hDC );i=0;
//TextLöschen Ende

xPos1 = LOWORD(lParam);
yPos1 = HIWORD(lParam);

xPosAlt=xPos1;
yPosAlt=yPos1;

hDC = GetDC( hWnd );
sprintf( PosText,MousePosition,xPos1,yPos1);
TextOut( hDC, xPos1, yPos1, PosText, lstrlen( PosText) );
ReleaseDC( hWnd, hDC );
//Repaint(hWnd,hDC);
break;

case WM_LBUTTONUP:

RepDat[i].xPos1=xPos1;
RepDat[i].yPos1=yPos1;

xPos1=xPos2;
yPos1=yPos2;
xPos2=LOWORD(lParam);
yPos2=HIWORD(lParam);

RepDat[i].xPos2=xPos2;
RepDat[i].yPos2=xPos2;

i++;

iCount = sizeof(RepDat);

if (xPos1 > 0 && yPos1 > 0)
InvalidateRect(hWnd,NULL,FALSE);
//Repaint(hWnd,hDC);i=0;
break;

case WM_PAINT:

hDC=BeginPaint(hWnd,&ps);
SelectObject(hDC, stift);
MoveToEx(hDC, xPos1, yPos1, NULL);
LineTo(hDC, xPos2, yPos2);
DeleteObject(stift);


EndPaint(hWnd,&ps);
//Repaint(hWnd,hDC);i=0;

break;


case WM_CLOSE:
DestroyWindow(hWnd);
break;

case WM_DESTROY:
PostQuitMessage(0);
break;
}

return DefWindowProc(hWnd, iMsg, wParam, lParam);
}

void Repaint(HWND hWnd, HDC hDC)
{
PAINTSTRUCT ps;
for (i=0; i<sizeof(RepDat) / sizeof(RepDat[0]); i++)
{
HPEN stift = CreatePen( PS_SOLID, 5, RGB(RepDat[i].rot,RepDat[i].gruen,RepDat[i].blau));
hDC=BeginPaint(hWnd,&ps);
SelectObject(hDC, stift);
MoveToEx(hDC, RepDat[i].xPos1, RepDat[i].yPos1, NULL);
LineTo(hDC, RepDat[i].xPos2, RepDat[i].yPos2);
DeleteObject(stift);
EndPaint(hWnd,&ps);
}
}

Crushinator
2003-11-14, 23:07:28
Vermisse Inhalt von "stringtext.h", um es unkompliziert in mein Projekt reinzuquätschen. Her damit. :jump2:

Matrix316
2003-11-14, 23:44:27
#define Titel Load_String(IDS_STRING1)
#define Fehler Load_String(IDS_STRING2)
#define Fenstertext Load_String(IDS_STRING3)
#define InfoTitel Load_String(IDS_STRING4)
#define InfoText Load_String(IDS_STRING5)
#define MousePosition Load_String(IDS_STRING6)


Stringtable

/////////////////////////////////////////////////////////////////////////////
//
// String Table
//

STRINGTABLE DISCARDABLE
BEGIN
IDS_STRING1 "Das ist ein Fenster"
IDS_STRING2 "Klasse nicht Registriert"
IDS_STRING3 "Fenster wurde gemacht von mir."
IDS_STRING4 "Info Dialog"
IDS_STRING5 "Hallo Info Copyright"
IDS_STRING6 "Pos.: X = %04d, Y = %04d iCount=%d"
END

#endif // Deutsch (Deutschland) resources
/////////////////////////////////////////////////////////////////////////////


Menu

/////////////////////////////////////////////////////////////////////////////
//
// Menu
//

IDR_MENU1 MENU DISCARDABLE
BEGIN
POPUP "&Datei"
BEGIN
MENUITEM "&Beenden", ID_DATEI_BEENDEN
END
POPUP "&Fenster"
BEGIN
MENUITEM "Bildschirm löschen", ID_FENSTER_BILDSCHIRMLSCHEN
POPUP "Linienfarbe ändern"
BEGIN
MENUITEM "rot", ID_FENSTER_LINIENFARBENDERN_ROT

MENUITEM "gruen", ID_FENSTER_LINIENFARBENDERN_GRUEN

MENUITEM "blau", ID_FENSTER_LINIENFARBENDERN_BLAU

MENUITEM "schwarz", ID_FENSTER_LINIENFARBENDERN_SCHWARZ

MENUITEM "gelb", ID_FENSTER_LINIENFARBENDERN_GELB

END
END
POPUP "&?"
BEGIN
MENUITEM "&info", ID__INFO
END
END


/////////////////////////////////////////////////////////////////////////////

Crushinator
2003-11-15, 04:24:45
:idea:

/* zu den globalen Vars */
int iCurrMem;

struct sRepaintDaten{int used; int rot; int gruen; int blau; int xPos1;
int yPos1; int xPos2; int yPos2;};
/* Einfachheitshalber von vornherein auf 200
Member begrenzt, Du solltest es später dynamisch mit malloc/realloc
versuchen */
struct sRepaintDaten RepDat[200];

Dann wäre noch das:

/* Array nullen */
memset(RepDat,0x0, sizeof(RepDat));
iCount = sizeof(RepDat) / sizeof(struct sRepaintDaten);

^^ In die WinMain direkt vor dem ShowWindow(hWnd, nShowCms); wobei so ein memset() beim dynamischen Array völlig fehl am Platz ist und iCount dann auch eher in die WndProc vor/nach *alloc gehört.

Für die WndProc kam mir natürlich folgendes in den Sinn:

case WM_LBUTTONDOWN:
//TextLöschen!
hDC = GetDC( hWnd );
SetTextColor(hDC, RGB(255,255,255));
sprintf( PosText,MousePosition,xPos1,yPos1, iCount);
TextOut( hDC, xPosAlt, yPosAlt, PosText, lstrlen( PosText) );
ReleaseDC( hWnd, hDC );
//TextLöschen Ende

xPos1 = LOWORD(lParam);
yPos1 = HIWORD(lParam);


xPosAlt=xPos1;
yPosAlt=yPos1;

/* Nicht vergessen */
Repaint(hWnd);

hDC = GetDC( hWnd );
/* iCount fehlte, deshalb kam 124896 */
sprintf( PosText,MousePosition,xPos1,yPos1, iCount);
TextOut( hDC, xPos1, yPos1, PosText, lstrlen( PosText) );
ReleaseDC( hWnd, hDC );
break;

case WM_LBUTTONUP:

xPos2=LOWORD(lParam);
yPos2=HIWORD(lParam);
if (iCurrMem < iCount)
{
RepDat[iCurrMem].used = 1;
RepDat[iCurrMem].xPos2=xPos1;
RepDat[iCurrMem].yPos2=yPos1;

if (!iCurrMem)
{
RepDat[iCurrMem].xPos1=xPos1;
RepDat[iCurrMem].yPos1=yPos1;
}

iCurrMem++;

RepDat[iCurrMem].xPos1=xPos2;
RepDat[iCurrMem].yPos1=yPos2;

}

if (iCurrMem>1)
{
InvalidateRect(hWnd,NULL,FALSE);
}

xPos1=xPos2;
yPos1=yPos2;
break;

case WM_PAINT:
Repaint(hWnd);
break;

last but not least:

void Repaint(HWND hWnd)
{
/* Was meinst Du, was passiert, wenn man einen globalen i hat und ihn auch
hier in der Schleife benutzt während man in der WndProc auch mit dem
selbigen i rumhantiert? :naughty: Genau: Man wird WAHNSINNIG */
int i;
HDC hDC;
PAINTSTRUCT ps;

hDC=BeginPaint(hWnd,&ps);
for (i=0; i<sizeof(RepDat) / sizeof(struct sRepaintDaten); i++)
{
/* nur benutzten Member nachmalen, bei Dyn-Array nicht notwendig */
if (RepDat[i].used)
{
HPEN stift = CreatePen( PS_SOLID, 5, RGB(RepDat[i].rot,
RepDat[i].gruen,RepDat[i].blau));
SelectObject(hDC, stift);
MoveToEx(hDC, RepDat[i].xPos1, RepDat[i].yPos1, NULL);
LineTo(hDC, RepDat[i].xPos2, RepDat[i].yPos2);
DeleteObject(stift);
}
}
EndPaint(hWnd,&ps);
}

Ich hoffe, ich habe Dir in meinem gerade "etwas" betrunkenen Zustand paar Ideen geben können. Nun darfst Du Dich mit den Farben und so'n Zeugs austoben, denn ich gehe jetzt ins Bett. http://home.t-online.de/home/bullitt667/smilies/data/uglywave.gif

Matrix316
2003-11-15, 10:33:42
Vielen Dank erstmal, ich probiers mal aus. :)

Matrix316
2003-11-15, 11:29:21
Aaaaalso: Es geht. Teilweise. ;)

Was nicht geht ist das Bildschirmlöschen, was man lösen könnte in dem man einfach alles mit weiß drübermalt. :D

Für die Farben, hab ich diese aus dem Struct entfernt und in der Repaint Funktion einfach jetzt 4 Parameter, einer für den Handle und dann die r,g und b Werte.

Jetzt ändert er die Farbe, aber nur bei einem Repaint. Wenn ich im Menü die neue Farbe anklicke muss ich auf dem Bildschirm nochmal klicken, damit diese geändert wird.

Was anderes ist, dass das Programm sehr gut funktioniert, wenn man laaaangsam klickt. Klickt man zu schnell, gibts Lücken zwischen den Linien.

Außerdem hab ich in der Lösung gesehen, dass das Zeichnen irgendwann aufhört, was mich zu einem neuen Gedanken geführt hat und zwar, dass wir bzw. ich es uns eigentlich viel zu kompliziert gemacht haben mit dem Struct und so, und dass es eigentlich ganz bestimmt eine ganz einfach Lösung für das ganze gibt!

Und zwar überleg ich mir jetzt den Struct komplett wegzulassen und stattdessen einfach einen 2 Dimensionalen Array zu nehmen! =) Dieser wird begrenzt und wenn er voll ist, ist Ende. Punkt. ;)

Außerdem wäre es wahrscheinlich am besten das Zeichnen von allem Komplett in EINER Funktion unterzubringen, auch den Text. Und beim Löschen, stellt man einfach alle Farben auf Weiß und gut ist.

Problem ist nur, warum oder wie kann man den Repaint direkt bei der Farbauswahl auslösen? Ich hab mal die Repaint Funktion bei dem Menüpunkt der Farben reingeschrieben, aber es wurde TROTZDEM erst geändert, als ich ins Bild geklickt habe...

Matrix316
2003-11-15, 17:18:45
Das mit dem nur array und Zeichnen nur in Repaint hat überhaupt nicht funktioniert...

Kann ich den WM_PAINT Aufruf auch z.B. bei der Farbauswahl machen?

Geht da was mit SendMessage oder so? :| :kratz:

Xmas
2003-11-15, 19:11:05
Ein Neuzeichnen löst man üblicherweise durch UpdateWindow aus, nicht mit SendMessage(... WM_PAINT ...)

UpdateWindow(hwnd);


Falls das nicht reicht, dann
InvalidateRect(hwnd, NULL, FALSE);
UpdateWindow(hwnd);

Matrix316
2003-11-15, 20:39:12
Hab gerade festgestellt, es reicht schon das InvalidateRect (das UpdateWindow ist ja in der Winmain)

Also hier mal der aktuelle Code ohne die Repaint Funktion.


include <windows.h>
#include <stdio.h>
#include "stringtext.h"
#include "resource.h"


const char *Fenster = "WinFenster";
int rot=255, gruen=125, blau=0;
int i,j,k,l;
int iCount;

//NEU
int iCurrMem;


//NEUENDE
struct sRepaintDaten{int used; int xPos1; int yPos1; int xPos2; int yPos2;};
struct sRepaintDaten RepDat[255]; //= {0,0,0,0,0,0,0};
/*Zugrff auf Inhalt des Structs
RepDat[i].xPos1
RepDat[i].xPos2
RepDat[i].yPos1
RepDat[i].yPos2
RepDat[i].rot
RepDat[i].gruen
RepDat[i].blau*/
LPCTSTR Load_String(unsigned int IDName);
BOOL CALLBACK DialogProc(HWND hDlg,UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK WndProcedure(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam);



int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCms)
{
WNDCLASSEX wndClass;
HWND hWnd;
MSG Msg;
HACCEL hAcl;

wndClass.cbSize=sizeof(WNDCLASSEX);
wndClass.style=CS_HREDRAW|CS_VREDRAW;
wndClass.lpfnWndProc=WndProcedure;
wndClass.cbClsExtra=0;
wndClass.cbWndExtra=0;
wndClass.hInstance=hInstance;

wndClass.hIcon=LoadIcon(GetModuleHandle(NULL),MAKEINTRESOURCE(IDI_ICON1));
wndClass.hIconSm=(HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON1),
IMAGE_ICON, 16, 16, 0);
wndClass.hCursor = LoadCursor(hInstance,MAKEINTRESOURCE(IDC_CURSOR1));
wndClass.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
wndClass.lpszMenuName=MAKEINTRESOURCE(IDR_MENU1);
wndClass.lpszClassName=Fenster;

if (!RegisterClassEx(&wndClass))
{
MessageBox(NULL,Fehler, 0,0);
return -1;
}

hWnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
Fenster,
Titel,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
640,
480,
NULL,
NULL,
hInstance,
NULL);

if(hWnd == NULL)
{
MessageBox(NULL, "Window Creation Failed!", "Error!",0);
return 0;
}

hAcl=LoadAccelerators(hInstance,MAKEINTRESOURCE(IDR_ACCELERATOR1));

//NEU
memset(RepDat,0x0, sizeof(RepDat));
iCount = sizeof(RepDat) / sizeof(struct sRepaintDaten);
//ENDNEU
ShowWindow(hWnd, nShowCms);
UpdateWindow(hWnd);




while(GetMessage(&Msg, NULL, 0, 0))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}

return 0;

}

LPCTSTR Load_String(unsigned int IDName)
{
static char buffer[255];
if (LoadString(GetModuleHandle(0),IDName,buffer,sizeof(buffer))<0)
{
return NULL;
}
else
return (LPCTSTR)buffer;
}


BOOL CALLBACK DialogProc(HWND hDlg,UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_INITDIALOG:

return TRUE;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDOK:
EndDialog(hDlg, IDOK);
break;
case IDCANCEL:
EndDialog(hDlg, IDCANCEL);
break;
}
break;
default:
return FALSE;
}
return TRUE;

}

LRESULT CALLBACK WndProcedure(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
static char PosText[128];
static int xPos1, yPos1, xPos2, yPos2;
HPEN stift = CreatePen( PS_SOLID, 5, RGB(rot,gruen,blau));

static int xPosAlt, yPosAlt;

switch(iMsg)
{
case WM_COMMAND:
switch (LOWORD(wParam))
{
case ID_DATEI_BEENDEN:
DestroyWindow(hWnd);
break;
case ID_FENSTER_BILDSCHIRMLSCHEN:
xPos1=xPos2=yPos1=yPos2=xPosAlt=yPosAlt=-1;

InvalidateRect(hWnd, NULL, FALSE);
//SetTextColor(hDC, RGB(255,255,255));
//rot=255;
//gruen=255;
//blau=255;

break;
case ID_FENSTER_LINIENFARBENDERN_ROT:
rot=255;
gruen=0;
blau=0;
InvalidateRect(hWnd,NULL,FALSE);
// Repaint(hWnd,rot,gruen,blau);
break;
case ID_FENSTER_LINIENFARBENDERN_GRUEN:
rot=0;
gruen=255;
blau=0;
InvalidateRect(hWnd,NULL,FALSE);
// Repaint(hWnd,rot,gruen,blau);
break;
case ID_FENSTER_LINIENFARBENDERN_BLAU:
rot=0;
gruen=0;
blau=255;
InvalidateRect(hWnd,NULL,FALSE);
// Repaint(hWnd,rot,gruen,blau);
break;
case ID_FENSTER_LINIENFARBENDERN_SCHWARZ:
rot=0;
gruen=0;
blau=0;
InvalidateRect(hWnd,NULL,FALSE);
// Repaint(hWnd,rot,gruen,blau);
break;
case ID_FENSTER_LINIENFARBENDERN_GELB:
rot=255;
gruen=255;
blau=0;
InvalidateRect(hWnd,NULL,FALSE);
// Repaint(hWnd,rot,gruen,blau);
break;
case ID__INFO:

int ret = DialogBox(GetModuleHandle(NULL),MAKEINTRESOURCE(IDD_DIALOG1), hWnd, DialogProc);

if(ret == -1)
{
MessageBox(hWnd, "Dialog failed!", "Fehler",MB_OK | MB_ICONINFORMATION);
}

break;
}

case WM_LBUTTONDOWN:
//TextLöschen!
hDC = GetDC( hWnd );
SetTextColor(hDC, RGB(255,255,255));
sprintf( PosText,MousePosition,xPos1,yPos1,iCount);
TextOut( hDC, xPosAlt, yPosAlt, PosText, lstrlen( PosText) );
ReleaseDC( hWnd, hDC );i=0;
//TextLöschen Ende

xPos1 = LOWORD(lParam);
yPos1 = HIWORD(lParam);

xPosAlt=xPos1;
yPosAlt=yPos1;

hDC = GetDC( hWnd );
SetTextColor(hDC, RGB(0,0,0));
sprintf( PosText,MousePosition,xPos1,yPos1,iCount);
TextOut( hDC, xPos1, yPos1, PosText, lstrlen( PosText) );
ReleaseDC( hWnd, hDC );

break;

case WM_LBUTTONUP:

xPos2=LOWORD(lParam);
yPos2=HIWORD(lParam);

//NEU
if (iCurrMem < iCount)
{
RepDat[iCurrMem].used = 1;
RepDat[iCurrMem].xPos2=xPos1;
RepDat[iCurrMem].yPos2=yPos1;

if (!iCurrMem)
{
RepDat[iCurrMem].xPos1=xPos1;
RepDat[iCurrMem].yPos1=yPos1;
}

iCurrMem++;

RepDat[iCurrMem].xPos1=xPos2;
RepDat[iCurrMem].yPos1=yPos2;

}



if (iCurrMem>1)
{
InvalidateRect(hWnd,NULL,FALSE);
}
//NEUENDE

xPos1=xPos2;
yPos1=yPos2;


//if (xPos1 > 0 && yPos1 > 0)
// InvalidateRect(hWnd,NULL,FALSE);

break;

case WM_PAINT:

int j;

hDC=BeginPaint(hWnd,&ps);
for (j=0; j<sizeof(RepDat) / sizeof(struct sRepaintDaten); j++)
{
if (RepDat[j].used)
{
HPEN stift = CreatePen( PS_SOLID, 4, RGB(rot,gruen,blau));

SelectObject(hDC, stift);
MoveToEx(hDC, RepDat[j].xPos1, RepDat[j].yPos1, NULL);
LineTo(hDC, RepDat[j].xPos2, RepDat[j].yPos2);
DeleteObject(stift);

}
}

InvalidateRect(hWnd,NULL,FALSE);

break;


case WM_CLOSE:
DestroyWindow(hWnd);
break;

case WM_DESTROY:
PostQuitMessage(0);
break;
}

return DefWindowProc(hWnd, iMsg, wParam, lParam);
}



Die Probleme sind noch dieselben: Bildschirminhalt geht nicht löschen, Lücken zwischen den Linien, wenn man zu schnell klickt.

Das mit den Lücken kann man lösen, wenn man den Array mit den Startwerten bei lbuttondown füllt und nur die endwerte im lButtonup macht, nur dann malt er nicht mehr neu (wobei mir gerade eine Idee gekommen ist... ;))...

Matrix316
2003-11-15, 20:59:33
Apropos Bildschirmlöschen: Kann ich net einfach ein großes weiß gefülltes Rechteck drüberklatschen in größe des aktuellen Bildschirms?

EDIT Löschen hat sich gerade erledigt. ;) Ich sag nur Invali....(.....TRUE)

Matrix316
2003-11-15, 21:22:47
Hier die Komplette Löschaktion. Leider bleibt links oben der Text stehen...:(


case ID_FENSTER_BILDSCHIRMLSCHEN:
xPos1=xPos2=yPos1=yPos2=-1;
k=1;
for (j=0; j<sizeof(RepDat) / sizeof(struct sRepaintDaten); j++)
{
RepDat[j].used = 0;
RepDat[j].yPos1=-1;
RepDat[j].yPos1=-1;
RepDat[j].yPos2=-1;
RepDat[j].yPos2=-1;

}

iCurrMem=0;
RepDat[iCurrMem].xPos1=xPos1;
RepDat[iCurrMem].yPos1=yPos1;
InvalidateRect(hWnd, NULL, TRUE);
UpdateWindow(hWnd);
break;

Matrix316
2003-11-16, 17:20:05
Also ich hab keine Ahnung warum es Lücken gibt, wenn man zu schnell klickt.

Das kann irgendwie nur an dem Array Liegen, aber warum???

Ich hab auch schon Probiert den Array beim Buttondown und beim Buttonup zu füllen, aber das hat nicht funktioniert...

Matrix316
2003-11-16, 18:04:52
Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahhhhhhhhhhhhhhhhhhh;D

Manchmal kann das komplizierte so einfach sein. ;)

Ich hab die Lösung für das Lückenproblem:

Einfach das

xPos2=LOWORD(lParam);
yPos2=HIWORD(lParam);

aus dem "case WM_LBUTTONUP:" ans Ende vom "case WM_LBUTTONDOWN:" setzen...

Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahhhhhhhhhhhhhhhhhhh :bonk:

Crushinator
2003-11-16, 22:30:06
Original geschrieben von Matrix316
Hier die Komplette Löschaktion. Leider bleibt links oben der Text stehen...:( :kratz2: Wie ist es damit?

case ID_FENSTER_BILDSCHIRMLSCHEN:
(...)
/* Wech damit
InvalidateRect(hWnd, NULL, TRUE);
UpdateWindow(hWnd);
*/
RedrawWindow(hWnd,NULL, NULL,
RDW_ERASE | RDW_INVALIDATE | RDW_FRAME |
RDW_NOCHILDREN);

Außerdem ist es IMHO sinvoller:

case WM_PAINT:

hDC=BeginPaint(hWnd,&ps);

/* Schleife
(...)
*/
/* Wo ist denn Endpaint geblieben
InvalidateRect(hWnd,NULL,FALSE);
*/

EndPaint(hWnd,&ps);

break;

matrix316@fh
2003-11-17, 09:30:14
Das ist natürlich noch cooler, ich werds mal probieren. ;)

Das mit dem EndPaint ist mir auch aufgefallen, obwohl es auch so läuft.

Wobei es nach einiger Zeit abstürzt...=)

Was ganz anderes: Wenn ich ein Tray icon einfüge, soll auch ein Popup Menü (für das icon) erstellt werden, nur wie mach ich das? Geht das auch über den Ressourceneditor oder "Manuell"?

Crushinator
2003-11-17, 14:50:04
Original geschrieben von matrix316@fh
Was ganz anderes: Wenn ich ein Tray icon einfüge, soll auch ein Popup Menü (für das icon) erstellt werden, nur wie mach ich das? Geht das auch über den Ressourceneditor oder "Manuell"?
Beispiel für dasselbe Icon, was Du in Deinem Fensterle benutzt: (Bei neuem Icon, muß man natürlich die ID des Neuen der LoadImage übergegeben, sonst alles gleich)

/* global oder static local */
NOTIFYICONDATA Trayinfo;

(...)

case WM_RBUTTONDOWN: // Nur als Beispiel
// add the program's icon to the tray
memset(&Trayinfo,0x0,sizeof(Trayinfo));
Trayinfo.cbSize =sizeof(Trayinfo) ;
Trayinfo.hWnd =hWnd; // form handle gets notification message
Trayinfo.uID =IDI_ICON1; // id of icon - passed back in wParam of message
Trayinfo.uCallbackMessage=MY_TRAY_ICON_MESSAGE; // our notification message
Trayinfo.hIcon =(HICON)LoadImage(GetModuleHandle(NULL),
MAKEINTRESOURCE(IDI_ICON1),
IMAGE_ICON, 16, 16, 0); // icon to display
strncpy (Trayinfo.szTip,Fenster,sizeof(Trayinfo.szTip)); // set tool tip text
Trayinfo.szTip[sizeof(Trayinfo.szTip)-1]='0';
Trayinfo.uFlags =NIF_MESSAGE | NIF_ICON | NIF_TIP ; // indicate modifications
Shell_NotifyIcon(NIM_ADD,&Trayinfo) ; // add it
break;

(...)

case WM_CLOSE:
if (Trayinfo.hWnd == hWnd)
/* Icon löschen */
Shell_NotifyIcon(NIM_DELETE, &Trayinfo);
DestroyWindow(hWnd);
break;

Für das Menü gibt's hier (http://www.codeproject.com/shell/StealthDialog.asp) ein Beispiel. Ich habe die CallBackMessage in meinem Code so benannt, damit man besser einen Bezug zu dem Code im Link herstellen kann, allerdings fehlt da im Link was, denn ein Kontextmenü wird IMHO besser so aufgerufen:

SetForegroundWindow(hWnd);
TrackPopupMenu(hMenu, ...);
/* :freak: ohne gibt's manchmal Probs */
PostMessage(hWnd, WM_NULL, 0, 0);

Viel Spaß damit. :)

Matrix316
2003-11-17, 19:45:50
Naja, den Quelltext für das Trayicon und das Menü hab ich schon, nur fehlt mir halt das Menü an sich, wo ich mit case ID_TRAY_HIDE: etc. zugreifen kann...

Crushinator
2003-11-17, 23:50:45
Achsooooo, achsooooo, achsoooooo...

Das läßt sich entweder wie jedes andere Menü im Ressourcen-Editor neu erzeugen oder man nimmt einfach ein bestehendes Menü und blendet das ein.

HMENU hmenu;
HMENU hmenuPopup;

hmenu = LoadMenu(hInstance,MAKEINTRESOURCE(IDR_MENU2));

(...)

hmenuPopup = GetSubMenu(hmenu, 0);
TrackPopupMenu(hmenuPopup,
TPM_BOTTOMALIGN,
pt.x, pt.y, 0, hWnd, NULL);

Alternativ kann man natürlich alles zur Laufzeit machen: (basiernd auf meinem letzten Code)

#define MY_TRAY_ICON_MESSAGE 31337
#define IDM_TRAY_SHOW 31336
#define IDM_TRAY_HIDE 31335
(...)

case MY_TRAY_ICON_MESSAGE:
switch (lParam)
{
case WM_RBUTTONDOWN:
case WM_CONTEXTMENU:
ShowContextMenu(hWnd);
break;
}
break;

(...)

void ShowContextMenu(HWND hWnd)
{
POINT pt;
HMENU hMenu;
GetCursorPos(&pt);
hMenu = CreatePopupMenu();
if(hMenu)
{
/* Menü-Item dynamisch bauen */
AppendMenu(hMenu, MF_STRING, IDM_TRAY_SHOW, "Sichtbar machen");
AppendMenu(hMenu, MF_STRING, IDM_TRAY_HIDE, "Verstecken");
SetForegroundWindow(hWnd);
TrackPopupMenu(hMenu, TPM_BOTTOMALIGN,
pt.x, pt.y, 0, hWnd, NULL );
PostMessage(hWnd, WM_NULL, 0, 0);
DestroyMenu(hMenu);
}
}

... in beiden Fällen müssen die Messages in der WndProc so abgefangen werden.

case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDM_TRAY_SHOW:
(...);
break;
case IDM_TRAY_HIDE:
(...);
break;
}

Crushinator
2003-11-18, 00:01:49
*bump*

Matrix316
2003-11-18, 19:38:21
Genau das hatten wir heute in der Vorlesung. ;)

Was ich mich nur Frage, warum stürzt es ab, wenn man zu viel Klickt und am Ende dann das Fenster minimiert und wieder vorholt?!

Crushinator
2003-11-18, 20:21:45
Original geschrieben von Matrix316
Was ich mich nur Frage, warum stürzt es ab, wenn man zu viel Klickt und am Ende dann das Fenster minimiert und wieder vorholt?! http://home.t-online.de/home/bullitt667/smilies/data/uglyconfused2.gif Bei mir passiert es nicht. :ratlos:

Kannst Du evtl. genau beschreiben, was man dafür tun muß? Ich habe es nämlich gerade mit RepDat[200] und 250 Klicks versucht, und es rief keinen Absurz nach min. und restore hervor. http://home.t-online.de/home/bullitt667/smilies/data/uglyparanoid.gif

Matrix316
2003-11-18, 22:13:57
Also ich hatte die Abstürze gestern an der FH und bei mir auch.

Ich hab eben mal RepDat auf 10 Begrenzt. Nach 10 Klicks hört er auf. Aber wenn man dann weiterklickt (20,30,40 oder 50 weitere ;)) wird plötzlich die bunte Linie schwarz und Dünn und es stürzt eben ab (ohne Fehlermeldung)

Wenn RepDat auf 255 steht, passiert der Absturz noch eher.

Ich wollte dann mal anstatt iCount einfach eine Variable nehmen und der einen Wert zuweisen (bei dem Auffüllen des Arrays) aber da stürzt es auch ab, wenn man nach dem Ende des Zeichnens einfach sinnlos weiterklickt...

Hier mal der aktuelle Code inkl. Trayicon mit Popup Menü (geht sogar ;)):


#include <windows.h>
#include <stdio.h>
#include "stringtext.h"
#include "resource.h"

#define ID_TRAYICON 1000
#define WM_TRAY_NOTIFICATION (WM_USER+100)



const char *Fenster = "WinFenster";
int rot=255, gruen=125, blau=0;
int i,j,k=0,l=5; //k ist für Textausgabe und l beschränkt die Zeichnerei
int iCount;

//NEU
int iCurrMem;


//NEUENDE
struct sRepaintDaten{int used; int xPos1; int yPos1; int xPos2; int yPos2;};
struct sRepaintDaten RepDat[10]; //= {0,0,0,0,0,0,0};
/*Zugrff auf Inhalt des Structs
RepDat[i].xPos1
RepDat[i].xPos2
RepDat[i].yPos1
RepDat[i].yPos2
RepDat[i].rot
RepDat[i].gruen
RepDat[i].blau*/
LPCTSTR Load_String(unsigned int IDName);
BOOL TrayMessage(HWND hwnd, DWORD iMsg, HICON hIcon, PSTR pszTip);
BOOL CALLBACK DialogProc(HWND hDlg,UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK WndProcedure(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam);



int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCms)
{
WNDCLASSEX wndClass;
HWND hWnd;
MSG Msg;
HACCEL hAcl;

wndClass.cbSize=sizeof(WNDCLASSEX);
wndClass.style=CS_HREDRAW|CS_VREDRAW;
wndClass.lpfnWndProc=WndProcedure;
wndClass.cbClsExtra=0;
wndClass.cbWndExtra=0;
wndClass.hInstance=hInstance;

wndClass.hIcon=LoadIcon(GetModuleHandle(NULL),MAKEINTRESOURCE(IDI_ICON1));
wndClass.hIconSm=(HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON1),
IMAGE_ICON, 16, 16, 0);
wndClass.hCursor = LoadCursor(hInstance,MAKEINTRESOURCE(IDC_CURSOR1));
wndClass.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
wndClass.lpszMenuName=MAKEINTRESOURCE(IDR_MENU1);
wndClass.lpszClassName=Fenster;

if (!RegisterClassEx(&wndClass))
{
MessageBox(NULL,Fehler, 0,0);
return -1;
}

hWnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
Fenster,
Titel,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
640,
480,
NULL,
NULL,
hInstance,
NULL);

if(hWnd == NULL)
{
MessageBox(NULL, "Window Creation Failed!", "Error!",0);
return 0;
}

hAcl=LoadAccelerators(hInstance,MAKEINTRESOURCE(IDR_ACCELERATOR1));

//NEU
memset(RepDat,0x0, sizeof(RepDat));
iCount = (sizeof(RepDat) / sizeof(struct sRepaintDaten))-1;
//ENDNEU
ShowWindow(hWnd, nShowCms);
UpdateWindow(hWnd);




while(GetMessage(&Msg, NULL, 0, 0))
{
if(TranslateAccelerator(hWnd, hAcl, &Msg) == 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
}

return 0;

}

LPCTSTR Load_String(unsigned int IDName)
{
static char buffer[255];
if (LoadString(GetModuleHandle(0),IDName,buffer,sizeof(buffer))<0)
{
return NULL;
}
else
return (LPCTSTR)buffer;
}




BOOL CALLBACK DialogProc(HWND hDlg,UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_INITDIALOG:

return TRUE;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDOK:
EndDialog(hDlg, IDOK);
break;
case IDCANCEL:
EndDialog(hDlg, IDCANCEL);
break;
}
break;
default:
return FALSE;
}
return TRUE;

}

BOOL TrayMessage(HWND hWnd, DWORD iMsg, HICON hIcon, PSTR pszTip)
{ NOTIFYICONDATA tnd;
tnd.cbSize = sizeof(NOTIFYICONDATA);
tnd.hWnd = hWnd;
tnd.uID = IDI_ICON2;
tnd.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP;
tnd.uCallbackMessage = WM_TRAY_NOTIFICATION;
tnd.hIcon = hIcon;
lstrcpyn(tnd.szTip, pszTip, sizeof(tnd.szTip));

BOOL res = Shell_NotifyIcon(iMsg, &tnd);
if (hIcon) DestroyIcon(hIcon);
return res;
}

LRESULT CALLBACK WndProcedure(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
RECT rect;


static char PosText[128];
static int xPos1, yPos1, xPos2, yPos2;

rect.left = xPos2; //linksobenX
rect.top = yPos2; //linksobenY
rect.right = xPos2+300; //rechtsuntenX
rect.bottom = yPos2+25; //rechtsunten>

HICON hIcon; POINT mouse; HMENU hMenu; //TrayIcon
HPEN stift = CreatePen( PS_SOLID, 5, RGB(rot,gruen,blau));
HFONT hFont = CreateFont(20,0,0,0,FW_NORMAL,
0,0,0,0,0,0,PROOF_QUALITY,DEFAULT_PITCH,"Times New Roman");

static int xPosAlt, yPosAlt;

switch(iMsg)
{
case WM_COMMAND:
switch (LOWORD(wParam))
{

//Acceleratortable
if (HIWORD(wParam)==1)
{
case ID_ACCEL40011:
int ret = DialogBox(GetModuleHandle(NULL),
MAKEINTRESOURCE(IDD_DIALOG1),
hWnd,
DialogProc);

if(ret == -1)
{
MessageBox(hWnd,
"Dialog failed!",
"Fehler",MB_OK | MB_ICONINFORMATION);
}
break;
}
//EndeAccel

//TrayIcon
case ID_TRAY_BEENDEN:
TrayMessage(hWnd, NIM_DELETE, NULL, NULL);
PostQuitMessage( 0 );
break;

case ID_TRAY_HIDE:
ShowWindow(hWnd, SW_HIDE);
break;

case ID_TRAY_SHOW:
ShowWindow(hWnd, SW_SHOW);
break;

case ID_TRAY_ABOUT:
DialogBox(GetModuleHandle(0),
MAKEINTRESOURCE(IDD_DIALOG1),hWnd,(DLGPROC)DialogProc);
break;
//TrayIconEnde




case ID_DATEI_BEENDEN:
DestroyWindow(hWnd);
break;
case ID_FENSTER_BILDSCHIRMLSCHEN:



k=0; //Text wird nicht geschrieben

xPos1=xPos2=yPos1=yPos2=-1;


for (j=0; j<sizeof(RepDat) / sizeof(struct sRepaintDaten); j++)
{
RepDat[j].used = 0;
RepDat[j].yPos1=-1;
RepDat[j].yPos1=-1;
RepDat[j].yPos2=-1;
RepDat[j].yPos2=-1;

}

iCurrMem=0;

RepDat[iCurrMem].xPos1=xPos1;
RepDat[iCurrMem].yPos1=yPos1;


InvalidateRect(hWnd, NULL, TRUE);
UpdateWindow(hWnd);

/* RedrawWindow(hWnd,NULL, NULL,
RDW_ERASE | RDW_INVALIDATE | RDW_FRAME |
RDW_NOCHILDREN);

//TextLöschen!
hDC=BeginPaint(hWnd,&ps);

SetTextColor(hDC, RGB(0,0,0));
sprintf( PosText,MousePosition,xPos1,yPos1);
SelectObject(hDC,hFont);
TextOut( hDC, xPosAlt, yPosAlt, PosText, lstrlen( PosText) );
//DrawText(hDC,MousePosition,strlen(PosText),&rect,DT_LEFT|DT_TOP);
DeleteObject(hFont);
ReleaseDC( hWnd, hDC );
EndPaint(hWnd,&ps);
//TextLöschen Ende */

break;
case ID_FENSTER_LINIENFARBENDERN_ROT:
rot=255;
gruen=0;
blau=0;
InvalidateRect(hWnd,NULL,FALSE);
// Repaint(hWnd,rot,gruen,blau);
break;
case ID_FENSTER_LINIENFARBENDERN_GRUEN:
rot=0;
gruen=255;
blau=0;
InvalidateRect(hWnd,NULL,FALSE);
// Repaint(hWnd,rot,gruen,blau);
break;
case ID_FENSTER_LINIENFARBENDERN_BLAU:
rot=0;
gruen=0;
blau=255;
InvalidateRect(hWnd,NULL,FALSE);
// Repaint(hWnd,rot,gruen,blau);
break;
case ID_FENSTER_LINIENFARBENDERN_SCHWARZ:
rot=0;
gruen=0;
blau=0;
InvalidateRect(hWnd,NULL,FALSE);
// Repaint(hWnd,rot,gruen,blau);
break;
case ID_FENSTER_LINIENFARBENDERN_GELB:
rot=255;
gruen=255;
blau=0;
InvalidateRect(hWnd,NULL,FALSE);
// Repaint(hWnd,rot,gruen,blau);
break;
case ID__INFO:

int ret = DialogBox(GetModuleHandle(NULL),MAKEINTRESOURCE(IDD_DIALOG1), hWnd, DialogProc);

if(ret == -1)
{
MessageBox(hWnd, "Dialog failed!", "Fehler",MB_OK | MB_ICONINFORMATION);
}

break;
}

case WM_CREATE:

hIcon=(HICON)LoadImage(GetModuleHandle(0),MAKEINTRESOURCE(IDI_ICON2),IMAGE_ICON, 16,16,0);
TrayMessage(hWnd, NIM_ADD, NULL, NULL);
TrayMessage(hWnd, NIM_MODIFY,hIcon, "Win32Fenster");
break;

case WM_TRAY_NOTIFICATION:
switch (lParam )
{
case WM_RBUTTONUP:
GetCursorPos(&mouse);
hMenu = GetSubMenu(
LoadMenu(GetModuleHandle(0),MAKEINTRESOURCE(IDR_MENU2)),0);
TrackPopupMenu(hMenu,0,mouse.x,mouse.y,0,hWnd,NULL);
break;
case WM_LBUTTONDBLCLK:
break;
}


case WM_LBUTTONDOWN:

k=1; //Text wird geschrieben

InvalidateRect(hWnd,NULL,TRUE);

xPos1 = LOWORD(lParam);
yPos1 = HIWORD(lParam);

xPosAlt=xPos1;
yPosAlt=yPos1;

xPos2=LOWORD(lParam);
yPos2=HIWORD(lParam);


break;

case WM_LBUTTONUP:



//NEU
if (iCurrMem < l)//iCount)
{
RepDat[iCurrMem].used = 1;
RepDat[iCurrMem].xPos2=xPos1;
RepDat[iCurrMem].yPos2=yPos1;

if (!iCurrMem)
{
RepDat[iCurrMem].xPos1=xPos1;
RepDat[iCurrMem].yPos1=yPos1;
}

iCurrMem++;

RepDat[iCurrMem].xPos1=xPos2;
RepDat[iCurrMem].yPos1=yPos2;

}

if (iCurrMem>1)
{
InvalidateRect(hWnd,NULL,FALSE);
}
//NEUENDE

xPos1=xPos2;
yPos1=yPos2;


break;

case WM_PAINT:



int j;

hDC=BeginPaint(hWnd,&ps);



for (j=0; j<sizeof(RepDat) / sizeof(struct sRepaintDaten); j++)
{
if (RepDat[j].used)
{
HPEN stift = CreatePen( PS_SOLID, 4, RGB(rot,gruen,blau));

SelectObject(hDC, stift);
MoveToEx(hDC, RepDat[j].xPos1, RepDat[j].yPos1, NULL);
LineTo(hDC, RepDat[j].xPos2, RepDat[j].yPos2);
DeleteObject(stift);

}
}

if (k==1)
{

SelectObject(hDC,hFont);
SetTextColor(hDC, RGB(0,0,0));
sprintf( PosText,MousePosition,xPos1,yPos1);
TextOut( hDC, xPosAlt, yPosAlt, PosText, lstrlen( PosText) );
//DrawText(hDC,MousePosition,strlen(PosText),&rect,DT_LEFT|DT_TOP);
DeleteObject(hFont);
ReleaseDC( hWnd, hDC );

EndPaint(hWnd,&ps);

}
InvalidateRect(hWnd,NULL,FALSE);
EndPaint(hWnd,&ps);
break;

case WM_CLOSE:
DestroyWindow(hWnd);
break;

case WM_DESTROY:
TrayMessage(hWnd, NIM_DELETE, NULL, NULL);
PostQuitMessage(0);
break;
}

return DefWindowProc(hWnd, iMsg, wParam, lParam);
}

Crushinator
2003-11-19, 11:34:56
Ohne jetzt den Code verifiziert zu haben fällt mir auf, daß in WM_PAINT a) ein EndPaint zuviel (in der Schleife) drinn zu sein scheint und b) daß InvalidateRect innerhalb von WM_PAINT "etwas" an Rekursivität erzeugt. =)

Matrix316
2003-11-19, 18:21:46
Also ich hab mal das EndPaint im if... und das invalidate... gelöscht, aber es stürzt immer noch ab...:(

PS.: Als OS Windows 2000 SP4!

Crushinator
2003-11-19, 19:16:36
;( Kannst Du mir das Projekt bitte kurz zumailen? Dann kann ich's in aller Ruhe analysieren, die Adresse hast Du ja noch. (Hab' btw. auch Win2K SP4)

Matrix316
2003-11-19, 19:23:04
Projekt ist unterwegs.

Eine Frage noch: Wenn ich mit Draw Text den Text schreibe, dann übersetzt er irgendwie nicht die Position, sondern schreibt %04D hin anstatt den Wert...:kratz:

Matrix316
2003-11-20, 10:06:19
Aaaalso: Es stürzt immer noch ab. Dass vielleicht ein paar breaks fehlten kann sein. ;) Wann ich jetzt den "stift" deklariere ist doch eigentlich egal, da er ja in WM Paint selcted und deleted wird.

Crushinator
2003-11-20, 10:26:40
Naja, wenn CreatePen aufgerufen wird, reserviert Windoofs für den Prozeß einen Pen. Wenn dieser nicht explizit vor einem neuen CreatePen wieder freigegeben wird, wir ein neuer CreatePen einfach einen weiteren Pen alloziieren. Außerdem war das eine Vermutung, denn bei mir sürzte es nicht ab sondern verhielt sich beim Zeichnen der Linien etwas zu komisch. Nach dem entfernen vom unbenutzten CreatePen war das Verhalten weg. :ratlos:

Matrix316
2003-11-20, 10:34:33
Also ich habs jetzt mal so gemacht, dass der Text am Ende der Linie bleibt und sich nicht mehr ändert:



case WM_PAINT:

int j;

hDC=BeginPaint(hWnd,&ps);

for (j=0; j<sizeof(RepDat) / sizeof(struct sRepaintDaten); j++)
{
if (RepDat[j].used)
{




HPEN stift = CreatePen( PS_SOLID, 4, RGB(rot,gruen,blau));

SelectObject(hDC, stift);
MoveToEx(hDC, RepDat[j].xPos1, RepDat[j].yPos1, NULL);
LineTo(hDC, RepDat[j].xPos2, RepDat[j].yPos2);
DeleteObject(stift);

rect.left = RepDat[j].xPos2; //linksobenX
rect.top = RepDat[j].yPos2; //linksobenY
rect.right = RepDat[j].xPos2+300; //rechtsuntenX
rect.bottom = RepDat[j].yPos2+25; //rechtsuntenY

}
}

if (k==1)
{

SelectObject(hDC,hFont);
SetTextColor(hDC, RGB(0,0,0));
sprintf( PosText,MousePosition,xPos1,yPos1);
DrawText(hDC,PosText,strlen(PosText),&rect,DT_LEFT|DT_TOP);
DeleteObject(hFont);
ReleaseDC( hWnd, hDC );

}

EndPaint(hWnd,&ps);
break;


Dazu muss auch noch ein InvalidateRect(hWnd,NULL,TRUE); an den Anfang von WM_...Buttonup sonst schreibt er den Text zweimal. Ach ja und das Invalidate... bei LButtondown kann weg. :)

Trotzdem stürzt es immer noch ab, wenn man zu lange klickt (nach dem Ende des Zeichnen), wobei ich jetzt länger klicken musste...;)

Der ganze Bildschirm wird dann weiß und die vorhandene bunte Linie erscheint links oben als eine schwarze dünne Linie...:kratz2:

Crushinator
2003-11-20, 12:36:07
Ich glaub' ich hab's: Ich stellte fest, daß selbst bei jedem Mousemove extra "Kernelspeicher" belegt wird. :o Also, fing ich an, nach Lecks zu suchen mit dem Ergebnis:

HFONT hFont = CreateFont(20,0,0,0,FW_NORMAL,
0,0,0,0,0,0,PROOF_QUALITY,DEFAULT_PITCH,"Times New Roman");

...wird so ziemlich bei jeder Message (auch MouseMove) ausgelöst und natürlich nicht wieder korrekt Deleted, weil die Zeile anfangs der WndProc ohne jegliche case ... steht. :nono:

Als ich die Zeile direkt /edit: in dem

if (k==1)
{
/* hier */
...
}

bei WM_PAINT setzte, war's vorbei mit dem Speicherleck.

http://home.t-online.de/home/bullitt667/smilies/data/uglyhammer2.gif

Matrix316
2003-11-20, 14:12:09
Hmmmm das könnte es gewesen sein! Zumindest stürzt es nicht mehr ab, auch wenn man sehr lange klickt. ;D

Danke für die viele Arbeit, auch wenn ich nicht verstehe, was an dem Auffüllen des Structes so schlimm sein soll? Er wird ja erst im case... selected...:kratz::kratz2:

Crushinator
2003-11-20, 15:04:31
Das läßt sich einfach erklären: Bisher wurde ja nicht nur eine lokale Variable deklariert und am Ende wieder freigegeben, sondern gleich mit der Funktion Create*** einem dann vom Kernel erstellt und alloziierten GDI-Objekt zugeordnet. Mit Select*** greift man sich Dieses und mit DeleteObject gibt man das in dem Augenblick der Variable zugewiesenen Objekt (in der GDI bzw. im Kernel) wieder frei. Tut man letzteres nicht, wird nach Beendigung der Funktion zwar der belegte Speicher für den Zeiger hFont freigegeben aber nicht jenes GDI/Kernel-Objekt, und es knallt logischerweise irgendwann, in dem Windows z.B. mit NICHT-Zeichnen bzw. NICHT-Beantwortung der Create*** Aufrufe (mit NULL) begegnet.

Wenn man vor dem Select (ich rede jetzt von dem HPEN von gestern) noch mal einen Create*** macht, wird das ursprüngliche Objekt ja nicht wieder freigegeben sondern nur ein Neues erstellt und stift zeigt dann auf das Neue. Das darauffolgende DeleteObject löscht dann nur das gerade erzeugte und NICHT das Alte mit der Folge, daß auch hierbei der Prozeß irgendwann den für ihn vorgesehenen Ressourcen-Limit im Kernel sprengt.

Wenn man dazu die hohe Anzahl der versendeten Nachrichten (man denke allein an WM_MOUSEMOVE bzw. WM_MOUSEOVER) an so ein Fenster und die damit verbundenen Aufrufe der WndProc, - welche bisher immer ein Create*** ohne DeleteObject ausgeführt haben - vor Augen hält, hört sich das ganze nicht mehr so unrealistisch an. =)

Matrix316
2003-11-20, 17:11:18
Aaaaaha. Wieder was dazugelernt. ;D :D