
Crush
Mitglieder-
Gesamte Inhalte
2048 -
Benutzer seit
-
Letzter Besuch
Inhaltstyp
Profile
Forum
Downloads
Kalender
Blogs
Shop
Alle Inhalte von Crush
-
Ok, anderer Vorschlag: Nimm einen Message-Schnüffler und Zeichne mal die Messages die beim Minimizen & Maximizen so verschickt werden auf. Versuche einen von diesen Messages abzufangen und hier den Update reinzubasteln. Ich habe mich auch schon gefragt, wie ich mich in die Message-Queue einklinken könnte, sodaß ich zuerst alle Signale filtern kann bevor irgendwas ausgelöst wird. Wenn Du das irgendwie hinkriegen solltest, würd´s mich interessieren wie. Darfst Du keine MFC verwenden oder willst Du das nicht? Härteste Lösung wäre es einen Timerprozess laufen zu lassen, der die Größe und den Status des Fensters ausliest. Beim Ändern zu Normalgröße mußt Du halt dann das Bild selber neu blitten. CWnd *pmeinWindow = FindWindow(NULL, _T("Name von Meinemwindow")); dann kannst Du ja hiermit ordentlich weiterarbeiten! <FONT COLOR="#a62a2a" SIZE="1">[ 23. Oktober 2001 10:35: Beitrag 3 mal editiert, zuletzt von Crush ]</font>
-
Ich meine auch, daß Du um das OnPaint nicht drumrum kommst. "The system sends an internal WM_PAINT message only once. After an internal WM_PAINT message is returned from GetMessage or PeekMessage or is sent to a window by UpdateWindow, the system does not post or send further WM_PAINT messages until the window is invalidated or until RedrawWindow is called again with the RDW_INTERNALPAINT flag set." Die Nachricht wird halt aufgenommen und ins Nirvana geschickt, bevor sie Dein Fenster erreicht. Offensichtlich ist Onpaint dran schuld, weil hier die Paint-Message abgefangen wird. Vielleicht würde es klappen, wenn Du hier RedrawWindow() mit dem komischen Flag am Ende aufrufst?!?!? Oder besser noch das ganze in UpdateWindow() refreshen lassen. <FONT COLOR="#a62a2a" SIZE="1">[ 23. Oktober 2001 09:36: Beitrag 3 mal editiert, zuletzt von Crush ]</font>
-
Wer kann helfen: Progress Bar (Fortschrittsbalken)
Crush antwortete auf DeBrainBoy's Thema in C und C++
Ziehe eine Statusanzeige aufs Edit-Window, Links-Strg-W: Member-Variable m_Progress1 (z.B.) vergeben. zum Austesten, damit man mal sieht, ob auch alles richtig klappt, habe ich einen Slider m_slider1 und ein Edit-Fenster m_edit1 genauso erstellt. Beim Slider im Register Nachrichtenzuordnung NM_CUSTOMDRAW auswählen. Doppelklick auf den Slider fügt die DDX-Routine entsprechend in den Source ein. Dort schreibst Du dann nur noch: m_slider1.SetRange(0,100,true); // um den Bereich für den Slider festzulegen int pos=m_slider1.GetPos(); // Slider Position abfragen CString String1; itoa(pos,String1.GetBuffer(3),10); // 10 ist der Radix, d.h. Zahlenbasis 10=normale Dezimalzahlen; 16=Hexadezimalausgabe. Die Zahl bei Getbuffer gibt an, wieviel Stellen im CString fürs Konvertieren verwendet werden dürfen. Ist die Ausgabe größer als diese Zahl, stürzt das Programm ab, also immer passend oder größer wählen! m_Edit1.SetWindowText(String1); // Text ausgeben m_Progress1.SetRange(0,100); // Bereich vom Fortschrittsbalken setzen m_Progress1.SetPos(pos); // Position des Balkens festlegen Jetzt kannst Du schon das Programm starten. Ziehst Du nun am Slider rum, siehst Du wie der Fortschrittbalken entsprechend verändert wird und der Wert unten noch im Klartext ausgegeben wird. Man kann natürlich das ganze auch Hard-Coden, aber das verbraucht nur irre Zeit, man muß sich direkt mit den Resourcen rumschlagen und verbringt mehr Zeit damit das Drumrum zum Laufen zu bringen, als die simple Abfrage fertigzustellen. Also soweit möglich mit Controls und Direct-Data-Exchange arbeiten empfehle ich (auch bei Pop-Up-Windows). Vielleicht noch als Anmerkung: Möchte man einen pixelgenauen Fortschrittsbalken kann man das mit Blitting-Routinen machen, z.B. so: // m_Progress1.SetPos(pos); // diese Zeile rauswerfen und stattdessen sowas reinschreiben: RECT newrect; CDC*pcdc=m_Progress1.GetWindowDC(); // Display-Kontext holen pcdc->GetWindow()->GetClientRect(&newrect); // Den Bereich in newrect setzen pcdc->FillSolidRect(&newrect,0); // erst mal mit schwarz ausfüllen (0xBBGGRR=blau, grün, rotanteil) newrect.right=(newrect.right-newrect.left)*pos/100; // da pos mit 100 berechnet wird einfach so die richtige Größe rausfinden pcdc->FillSolidRect(&newrect,0xffffff); // mit weiß nochmal den selektierten Bereich nachzeichnen. So lassen sich auch übrigens wunderbar Farb-Einstellungen erstellen: alle FillSolidRect()-Zeilen mit // ausklammern und statt dem ersten das hier reinschreiben: pcdc->FillSolidRect(&newrect,255/100*pos<<16); // blau hoch und runterzählen ... aber ich glaube jetzt schweife ich zuviel vom Thema ab! <FONT COLOR="#a62a2a" SIZE="1">[ 23. Oktober 2001 09:15: Beitrag 7 mal editiert, zuletzt von Crush ]</font> -
Also ich hab mir das Ding nicht angeschaut, aber ich weiß auch noch, daß bei Borland die String-Compare Funktionen teilweise anders interpretiert werden, also verschiedene Rückgabewerte liefern im Gegensatz zum Studio. Bestimmt liegt hier der Hund begraben. Ansonsten ist fast alles irgendwie kompatibel. Achso, die Namen müssen eventuell noch geändert werden, weil Borland liebend gerne ein T vor alle Funktionen stellt, damit diese auch richtig eingebunden und verarbeitet werden. Also versuche lieber nicht die die cpps und hs von Microsoft dort zu verwenden - die haben alle Vorsorge getragen, daß irgendwie das eine mit dem anderen nicht so richtig laufen will - so will man die Konkurrenz die eigenen Entwicklerschaar wohl vorenthalten.
-
Klar doch, such mal im Internet nach HelpPC, da ist alles wichtige übers Bios und IRQs, Assembler und C erklärt! Also COM1 sammelt scheints über 3F8, 2F8 die Bits zusammen (per Handshaking) und dort kannst Du dann auch abfragen - vielleicht auch noch über das Scratch PAD Register 3FF 2FF - frag mich aber nicht was das schon wieder sein soll (weiß ich doch selber nicht). Wenn Du die Pinbelegung hast kannst Du über 3FA/2FA, 3FB/2FB, 3FC/2FC, 3FD/2FD, 3FE/2FE noch weitere Bits von den Ports ablesen. <FONT COLOR="#a62a2a" SIZE="1">[ 21. Oktober 2001 19:25: Beitrag 2 mal editiert, zuletzt von Crush ]</font>
-
Das Referenzen und Variablen auch nur Zeiger sind beweist übrigens der Assembler-Part in diesem Thread, den byte ptr sind nunmal Zeiger auf byte: http://217.115.144.9/cgi-bin/ubbcgi/ultimatebb.cgi?ubb=get_topic&f=21&t=000387#000002 Also bin ich mit meinem Modell absolut nah dran an der Realität =:-)
-
Also normaler kann man das über die Funktion bdos() und int86() machen (steht in meinen Büchern und der MSDN) aber ich konnte nirgendwo diese Funktionen includen (komisch, aber auch egal) denn es ist viel eleganter und einfacher das ganze im Inline-Assembler zu machen: int inputbyte=0; unsigned int y=0x80000000; CString port; __asm { /* 279, 379, 3bd sind die Printer Port status Register Bit / Pin 0 =1 -> Timeout 3 15 4 13 5 12 6 10 7 11 278, 378, 3bc sind die Data Register vom Printer Ein Byte wird übergeben, wobei bit 0-7 Pin 2-9 auf dem Parallel-Port entsprechen 3be ist das Printer Control register Bit / Pin 0 1 1 14 2 16 3 17 4 0=IRQ disable ; 1=IRQ enable */ push ax push dx mov dx,0x3bc ; je nachdem auch entweder 278, 378 oder halt 3bc (Port im Bios) in al,dx; mov byte ptr inputbyte,al mov dx,0x3bd in al,dx; mov byte ptr inputbyte+1,al mov dx,0x3be in al,dx; mov byte ptr inputbyte+2,al pop dx pop ax } do { if (inputbyte&y) port+="1"; else port+="0"; } while (y>>=1); m_Edit1.SetWindowText(port); // CString irgendwo ausgeben m_Edit1.UpdateWindow(); // falls nötig Sind die Ports kleiner als 255 kann man die auch direkt eintippen: in al,10; mov byte ptr inputbyte,al Übrigens ist das auch der Beweis für ein anderes Forum, daß Referenzen auch Pointer sind!!! ( http://217.115.144.9/cgi-bin/ubbcgi/ultimatebb.cgi?ubb=get_topic&f=21&t=000386&co unterhit=yes ) Bei Borland klappt das vielleicht ja auch mit dem Int86(), leider weiß ich die genaue Interrupt-Nr vom Bios nicht und die entsprechende Registerbelegung um den Parallelport abzufragen (war auch zu faul zum Suchen), falls Du das noch rausfinden solltest, schreibs in diesem Thread noch irgendwo rein. Deshalb nur das Prinzip: #include <stdio.h> #include <dos.h> // Ich glaube das hier ist für int86() notwendig struct wreg { unsigned int ax; unsigned int bx; unsigned int cx; unsigned int dx; unsigned int si; unsigned int di; unsigned int cflag; }; struct breg { unsigned char al, ah; unsigned char bl, bh; unsigned char cl, ch; unsigned char dl, dh; }; union reg { struct wreg x; struct breg h; }; #define INTERRUPT 0x3bc; union reg inregs,outregs; inregs.h.ah=0x30; inregs.x.bx=0x3523; int86(INTERRUPT,&inregs,&outregs); usigned int Abgefragterwert=inregs.x.ax; Naja, irgendwie so sollte das jedenfalls klappen. Die DOS-Funktionen bdos() ruft man auch mit dieser Regs-Konstruktion auf, aber wie Du siehst ist das obere Beispiel etwas eleganter und schlanker, wodurch auch übersichtlicher. Assembler spart halt viel Zeit, Sourcecode und Ärger wenn´s um Hardware-Zugriffe geht. Beim Borland kann man das auch irgendwie so definieren, vielleicht heißt nur die initialisierung anders als __asm, bei manchen Compilern und Konstruktionen ist es notwendig __asm vor JEDER EINZELNEN ASSEMBLER-ZEILE zu schreiben, damit auch alles richtig läuft. Ich arbeite halt mit Studio ... <FONT COLOR="#a62a2a" SIZE="1">[ 21. Oktober 2001 19:10: Beitrag 2 mal editiert, zuletzt von Crush ]</font>
-
Das war leider die Wahrheit und der Stand vor ca. 1-2 Jahren aus einer Veröffentlichung vom Arbeitsamt (und wer sollte das denn besser wissen?) im Internet ( http://www.arbeitsamt.de/hst/international/greencard.html ). Vor kurzem kam im Stern ein Interview mit dem ersten Greencard-Mann (der aus Indonesien kam!). Die Leute glauben, da kommen lauter Computer-Inder, das ist nicht richtig, die kommen von überall her - man hat halt irgendwie gerne von den Indern gesprochen, wieso auch immer. Ich bin kein Mensch der Frust hat, sondern die Fakten sieht, erkennt, gerne zitiert und sogar mal nen Link postet ... ich habe die Ausbildung vor einem halben Jahr absolviert und meine das Geld auch wert zu sein - sowie auch einige andere hier im Thread (ok, sind vielleicht nicht tausende, aber doch 1-2% der FIAEs). <FONT COLOR="#a62a2a" SIZE="1">[ 21. Oktober 2001 13:17: Beitrag 1 mal editiert, zuletzt von Crush ]</font>
-
Stimmt nicht. Nach Gesetz muß für einen Greencard-Mann eine günstige Wohnung gestellt werden und eine Garantiegehalt von 100.000 DM Minimum (JA RICHTIG GEHÖRT - DAS IST GESETZ) mit einer 1-Jahres-Beschäftigungsgarantie (Minimum). Ich sag´s doch immer: Wir sollten uns alle mal einen Turban kaufen, umtaufen lassen, etwas bräunen und die indonesische Staatsbürgerschaft annehmen, dann ginge es allen besser!
-
Ist ja auch so toll, daß die Motorrad-Fahrer nicht angeschnallt mit Überschallgeschwindigkeit durch die Gegend rauschen und rechts überholen können ... Ernsthaft, ob der Mann schnell oder langsam gefahren ist ist durch das Foto noch nicht bewiesen. Es gibt auch Leute, die in Nachdenklichkeit und Konzentriertheit die Zunge unbewußt raushängen lassen (oder rausstrecken) - z.B. ICH =:-? und das könnte natürlich als Beleidung aufgefaßt werden. Ich habe mal eine Frau kennengelernt, die bei Konzentration die Nase mit der Zunge berührt hat und dann immer wieder die Zunge ein- und auf-"gerollt" hat, bzw. dick und dünn gemacht hat. Das konnte man irgendwie auf den ersten Blick überhaupt nicht zuordnen. Wäre allerdings für jeden Sekundenhingucker eine eindeutige Beleidigung. Vielleicht hat der Mann sich nur so konzentriert, die Geschwindigkeitsbeschränkung einzuhalten? Doch was ist eine Beleidigung? Wenn ich die Hände an die Ohren halte und mit aufgreissenen Augen mit den Fingern flattere??? Oder die Backen aufplustere? Oder auch nur mich mal am Kopf kratze? Ich finde einer der beleidigt ist durch solche "Gestik" drückt dadurch doch vor allem seine subjektive Auffassung zu Tage - und wenn einer meint alle wollen ihn Ärgern, dann kann man schnell etwas ausfindig machen, an dem man sich aufhängt. Wenn Polizisten die "Beamtenbeleidigung" einklagen können, kann ich eigentlich als Privatmann meine Privatbeleidigung einklagen, z.B. wenn mich jemand beim Grüßen nur böse anschaut? Also nichtverbale Beleidigungsformen halte ich für sehr fragwürdig. Übrigens geht mal alle nach Mexico, hebt mal die rechte Hand leicht auf etwas über Kopfhöhe an und dann winkt mit rotierendem Handgelenk mal einem Polizisten dort freundlich zu: Dafür kommt man in den Knast oder wird gleich auf der Straße umgenietet, weil das heißt auf deutsch: "Du Sau phiggst Deine Mutter!" was hier zu deutschen Landen als liebenswertes "Hallo!" aufgenommen wird. Es gibt noch ein paar andere lustige Gestiken die in Deutschland harmlos sind, jedoch in diversen Kulturen zu äußersten Reaktionen führen können. Laßt doch mal den Polizisten dort Urlaub machen. Ein Bekannter von mir war mal 2 Jahre in Mexico - und weil er nicht rasiert war mußte er sich während der Tageszeit in einer belebten Fußgängerzone KOMPLETT NACKT AUSZIEHEN (wenn er nicht erschossen werden wollte ... vom Polizisten). Dann hat man erst seine Sachen gemütlich durchsucht als sein Lümmel freiluft schnappte... vielleicht sah er als Tramper aus wie ein Drogendealer (hihi). Da hat ihn aber keiner wegen Erregung öffentlichen Ärgernisses verklagt (nackig auf der Straße rumrennen)! In China gibt´s auch eine ganz bösartige Handbewegung für "Hallo ich bin fremd hier!", da sollte man mit Gestik extrem vorsichtig sein, möchte man nicht Mao Tsetong geopfert werden. Leute aus venezuelaischen Inselkulturen haben auch eine extrem beleidigende Gesichtsmimik für uns Europäer. Die reißen wild die Augen auf, Strecken die Zunge raus und wackeln noch damit während sie die Backen aufplustern und mit der Hand unterm Arm Furzgeräusche machen und dabei wie Frösche in die Luft hüpfen und auf den Boden stampfen. Das ist bei denen ein Ausdruck der Freude!!! Bei uns würde ein Ausdruck des Entsetzens folgen. Ein Ausdruck der Beleidigung ist es, jemanden vor die Füße zu spucken - also in der Großstadt spuckt ständig einer von den Rauchern vor meine Füße (manchmal mit abartigen Brech- und Würggeräuschen im Vorfeld) und das darf man nicht als beleidigend auffassen??? Bei der nächsten Kontrolle als heimlicher Student von Inselkulturen outen und dann kann theoretisch einer beleidigenden deutschen Gestik nichts mehr anhaften. Man fühlt sich diesen Kulturen doch schließlich "verbunden"! <FONT COLOR="#a62a2a" SIZE="1">[ 21. Oktober 2001 19:34: Beitrag 4 mal editiert, zuletzt von Crush ]</font>
-
Der Computer hat Speicherstellen (Adressen) welche Daten beinhalten können (Werte). Anders ausgedrückt: Der Speicher des Computers beinhaltet Daten, die dadurch angesprochen werden können, daß jeder Stelle eine eindeutige Nummerierung vergeben ist, welche jedoch nicht unbedingt konstant zunimmt (Memory-Mapping-> oft zerstückelter/zusammengebastelter Speicher). Ich betrachte Referenzen als Kopien einer Adresse, auf die selbst nicht zugegriffen werden kann, sondern lediglich auf ihren Wert im Source kann man für dieselbe Referenz aber verschiedene Namen vergeben. Eine Referenz kann nicht verändert werden, deshalb ist das Const nicht für die Referenz ausschlaggebend, sondern für den Wert, den sie beinhaltet. Deshalb werden auch Referenzen verwendet um unnötige Kopien bei Funktionsaufrufen zu vermeiden (wo ja bei call-by-value die kompletten Wertinhalte auf den Stack kopiert werden und dann innerhalb der Funktion damit gearbeitet wird). Anbei gibt es auch noch das Schlüsselwort mutable mit dem konstante Werte als "kann nicht konstant sein" definiert werden (meist bei Klassenvariablen oder IO-Register oder Werte die auch von "außen" (andere Programme) oder auch von der Hardware verändert werden können ähnliches). Also im Grunde genommen ist das nur eine Frage der Betrachtungsweise, aber so wie Du´s siehst, warum nicht? Ein Zeiger ist Eine Adresse, die wiederum eine Adresse als Wert enthält, die den eigentlichen Wert beinhaltet. Deshalb kann man Zeiger auch hoch- und runterzählen oder halt einfach verändern und damit werden die Werte aus unterschiedlichen Adressen erreichbar. Zeiger auf Zeiger geht nochmal einen Schritt weiter. Der Zeiger(1) zeigt auf einen Zeiger(2) welcher auf eine Adresse zeigt(3), die einen Wert beinhaltet. Das hat Sinn, wenn mehrere Programme beispielsweise eine Änderung eines Zeigers mitbekommen sollen - und zwar parallel, damit nichts schiefläuft. Das wird z.B. bei dynamischen DLLs benutzt oder solche globalen Schnittstellen wie COM, DirectX oder ähnliche systemübergreifende Schnittstellen, die jedoch ausgetauscht werden können (oft während der Laufzeit). Es wird dann also bei einer Änderung lediglich Zeiger(2) verändert. Da alle Programme über Zeiger(1) arbeiten werden alle gleichzeitig "umgeschaltet". Vielleicht gibt es noch weitere Existenzberechtigungen (außer dem, die Newbies zu verwirren), aber mir ist da nix anderes aufgefallen. Die eigenschaft, Zeiger konstant zu halten, bzw. nicht zu vervielfältigen kann man übrigens durch sog. "Smart-Pointer" Classes erreichen. Da werden halt die Operatoren so überschrieben, daß immer nur ein aktueller Zeiger existiert, der halt irgendwo hinzeigt. Also jedenfalls so habe ich mir das ganze immer vorgestellt und so hat sich auch der ZeigerZeiger dann logisch einprägen können. Aber ich möchte nicht behaupten, daß das die politisch richtige Erklärung ist. Mal schaun, was andere so schreiben. <FONT COLOR="#a62a2a" SIZE="1">[ 21. Oktober 2001 10:17: Beitrag 3 mal editiert, zuletzt von Crush ]</font>
-
Soweit ich weiß war Rational Rose doch schweineteuer - gehört aber mit zum Besten. Allerdings ist Together fast noch besser und das Beste soll Objecteering sein, welches es sogar als eine Freeware-Version zum Download gibt.
-
Du hast es Dir geholt - ohne Anleitung? Wenn da nix dabei ist bei Konrad liegen immer wieder die Nitty-Gritties für ca. 20 DM aus zu diesem Thema. Aber es gibt auch noch 1000 weitere Bücher, die das VC++6 erklären und den Umgang damit vermitteln. Das wäre ein bissel viel alles hier beschreiben zu wollen - außerdem hängt das auch von der Edition ab. Es gibt meines Wissens minimum 3 Versionen und davon nochmal spezielle Studenten und Trial-Versionen, die alle mehr oder weniger eingeschränkt sind. Ein guter einstieg ist für ca. 250 DM die Standard Version und für den Otto-Normalverbraucher - die Du wahrscheinlich hast - auch absolut mehr als ausreichend. Schau Dich einfach mal nach entsprechender Literatur um. Irgendwo gab´s auch eine Online-Ausgabe vom Visual C++ 6.0 in 21 Tagen. Probier mal mit einer Suchmaschine was ausfindig zu machen. Wozu das ist? Zum schnellen Entwickeln und Testen von Software in der Programmiersprache C/C++ (inclusive Assembler) - wäre ja schlimm, wenn Du Dir was besorgst und nicht mal weißt, wozu das sein soll :-) Auf der Microsoft MSDN-Seite ist auch eigentlich alles abrufbar was die Funktionen und Möglichkeiten angeht - hoffentlich hast Du eine Flatrate um auch alles durchzuackern. <FONT COLOR="#a62a2a" SIZE="1">[ 20. Oktober 2001 00:29: Beitrag 1 mal editiert, zuletzt von Crush ]</font>
-
Also ich kenne Coop nur von einer pleite gegangenen Einzelhandelskettenskandal die als einizigste riesige Fischtanks hatten und man sich seinen Fisch lebendig rausangelte zum Mitnehmen :-)
-
Also mal sehn: Über den Registryeintrag "Defaulticon" kann man ein Icon an ein Objekt setzen. Eine aktualisierung des Icons auf dem System läuft über SHChangeNotify(SHCNE_UPDATEITEM, SHCNF_PATH, TEXT("C:\"), NULL); Ein Default-Icon für File Classes geht so z.B.: HKEY_CLASSES_ROOT .doc=AWordProcessor DefaultIcon=C:\MYDIR\MYAPP.EXE,1 Einen Context Menüeintrag erzeugt man für eine File-Extension so: HKEY_CLASSES_ROOT <applicationID> = <"description"> shell <verb> = <"menu-item text"> command = <"command string"> Command-Strings werden dann so gesetzt: HKEY_CLASSES_ROOT wrifile = Write Document shell open command = C:\Progra~1\Access~1\WORDPAD.EXE %1 print command = C:\Progra~1\Access~1\WORDPAD.EXE /p "%1" printto command = C:\Progra~1\Access~1\WORDPAD.EXE /pt "%1" "%2" "%3" "%4" der %1 parameter ist der Filename, %2 Printername, $3 Treibername und %4 Portname Das auslösen von Shell-Extension per Doppelclick (oder halt Einfachklick - je nach Einstellung) geht so: HKEY_CLASSES_ROOT .xyz="xyzfile" ShellNew NullFile="" . . . xyzfile="XYZ Picture" shell open command="C:\XYZ\XYZAPP.EXE %1 Die ClsID sollte auch mit einer GUID auf *.* erfaßt sein: HKEY_CLASSES_ROOT * = * shellex ContextMenuHandlers <name> = {00000000-1111-2222-3333-00000000000001} PropertySheetHandlers <name> = {00000000-1111-2222-3333-00000000000002} Oder auf einzelne Folders: Folder = Folder shellex DragDropHandlers <name> = {00000000-1111-2222-3333-00000000000004} CopyHookHandlers <name> = {00000000-1111-2222-3333-00000000000005} Um jetzt im Programm das ganze zu registrieren hier ein kleines Beispiel: #include <windows.h> #include <string.h> void main(void) { // // First, attempt to open the registry key where approved extensions are // listed. Note the extra slashes within the second parameter (the // registry path string). // long err; HKEY hkApproved; err = RegOpenKeyEx( HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved", 0, KEY_SET_VALUE, &hkApproved); if (err == ERROR_ACCESS_DENIED) { // // The user does not have permission to add a new value to this key. In this // case, a reasonable action would be to warn the user that some // application features will not be available unless an administrator // installs the application. If the shell extension is central to the // functioning of the application, tell the user that the install // can only be performed by an administrator, and stop the install. // } else if (err == ERROR_FILE_NOT_FOUND) { // // The key does not exist. This should only happen if setup is running // on Windows 95 instead of Windows NT, or if you are installing on an older // version of either operating system that does not have the new shell. // } else if (err != ERROR_SUCCESS) { // // Some other problem... // } else { // // The open of the key succeeded. Now register the new shell extension // under this key. This requires having the ProgID and string form of the // CLSID handy. // // // Assume that lpstrProgID contains our ProgID string. // LPSTR lpstrProgID = "My Bogus Class"; // // Assume that clsidExtension contains the CLSID struct. The code below // creates a string form this CLSID. If a string version of // the CLSID is already handy, skip this code. // CLSID clsidExtension = {0x11111111, 0x1111, 0x1111, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}; HRESULT hr; LPOLESTR lpolestrCLSID; CHAR rgchCLSID[40]; CoInitialize(NULL); hr = StringFromCLSID(clsidExtension, &lpolestrCLSID); // // StringFromCLSID returns a Unicode string, so convert to ANSI for // calling the registry. Note that on Windows NT you can call the Unicode // version of the registry API instead. // WideCharToMultiByte(CP_ACP, 0, lpolestrCLSID, -1, rgchCLSID, 40, NULL, NULL); CoTaskMemFree(lpolestrCLSID); CoUninitialize(); // // Now add the new value to the registry. // Note that each new shell extension CLSID must be registered here. // err = RegSetValueEx( hkApproved, rgchCLSID, 0, REG_SZ, (const BYTE *)lpstrProgID, strlen(lpstrProgID)); // // Finally, close the key. // err = RegCloseKey(hkApproved); } } Der Zugriff verläuft so: STDMETHODIMP CShellExt::Initialize( LPCITEMIDLIST pIDFolder, LPDATAOBJECT pDataObj, HKEY hRegKey) { // Initialize can be called more than once. if (m_pDataObj) m_pDataObj->Release(); // Save the object pointer. if (pDataObj) { m_pDataObj = pDataObj; pDataObj->AddRef(); // Get the file associated with this object, if applicable. STGMEDIUM medium; FORMATETC fe = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; UINT uCount; if(SUCCEEDED(m_pDataObj->GetData(&fe, &medium))) { // Get the file name from the HDROP. uCount = DragQueryFile((HDROP)medium.hGlobal, (UINT)-1, NULL, 0); if(uCount) DragQueryFile((HDROP)medium.hGlobal, 0, m_szFile, sizeof(m_szFile)); ReleaseStgMedium(&medium); } } // Duplicate the registry handle. if (hRegKey) RegOpenKeyEx( hRegKey, NULL, 0L, MAXIMUM_ALLOWED, &m_hRegKey); return NOERROR; } Hier sind die wichtigsten Funktionen kurz angesprochen: A shell extension handler must implement three functions: an entry point function (often called DllMain or LibMain), DllCanUnloadNow, and DllGetClassObject. DllCanUnloadNow and DllGetClassObject are essentially the same as they would be for any OLE in-process server DLL. The use of DllCanUnloadNow is shown in the following example: STDAPI DllCanUnloadNow(void) { // g_cRefThisDll must be placed in the instance-specific // data section. return ResultFromScode((g_cRefThisDll==0) ? S_OK : S_FALSE); } DllGetClassObject needs to expose the class factory for the object in the DLL. For more information about exposing the class factory, see the OLE documentation included in the Microsoft Platform Software Development Kit (SDK). The following example shows how to expose the class factory. // DllGetClassObject - a DLL entry point function used by // most in-process server DLLs. STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppvOut) { *ppvOut = NULL; // assume failure if (IsEqualIID(rclsid, CLSID_ShellExtension)) { return CShellExtSample_Create(riid, ppvOut); } else { return CLASS_E_CLASSNOTAVAILABLE; } } Und hier wie´s im Programm dann aussehen könnte: STDMETHODIMP CShellExt::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags) { UINT idCmd = idCmdFirst; char szMenuText1[64]; char szMenuText2[64]; char szMenuText3[64]; char szMenuText4[64]; BOOL bAppendItems=TRUE; if ((uFlags & 0x000F) == CMF_NORMAL) { lstrcpy(szMenuText1, "New menu item 1, Normal File"); lstrcpy(szMenuText2, "New menu item 2, Normal File"); lstrcpy(szMenuText3, "New menu item 3, Normal File"); lstrcpy(szMenuText4, "New menu item 4, Normal File"); } else if (uFlags & CMF_VERBSONLY) { lstrcpy(szMenuText1, "New menu item 1, Shortcut File"); lstrcpy(szMenuText2, "New menu item 2, Shortcut File"); lstrcpy(szMenuText3, "New menu item 3, Shortcut File"); lstrcpy(szMenuText4, "New menu item 4, Shortcut File"); } else if (uFlags & CMF_EXPLORE) { lstrcpy(szMenuText1, "New menu item 1, Normal File right click in Explorer"); lstrcpy(szMenuText2, "New menu item 2, Normal File right click in Explorer"); lstrcpy(szMenuText3, "New menu item 3, Normal File right click in Explorer"); lstrcpy(szMenuText4, "New menu item 4, Normal File right click in Explorer"); } else { bAppendItems = FALSE; } if (bAppendItems) { // Insert a separator InsertMenu(hMenu, indexMenu++, MF_SEPARATOR | MF_BYPOSITION, 0, NULL); // Insert the menu items InsertMenu(hMenu, indexMenu++, MF_STRING | MF_BYPOSITION, idCmd++, szMenuText1); InsertMenu(hMenu, indexMenu++, MF_STRING | MF_BYPOSITION, idCmd++, szMenuText2); InsertMenu(hMenu, indexMenu++, MF_STRING | MF_BYPOSITION, idCmd++, szMenuText3); InsertMenu(hMenu, indexMenu++, MF_STRING | MF_BYPOSITION, idCmd++, szMenuText4); // Must return the greatest menu item identifier plus one. return MAKE_HRESULT(SEVERITY_SUCCESS, 0, idCmd); } return NOERROR; } When the user selects one of the menu items added by a context menu handler, the shell calls the handler's InvokeCommand method to let the handler process the command. If multiple context menu handlers are registered for a file type, the value of the ContextMenuHandlers key determines the order of the commands. The InvokeCommand function in the following example handles the commands associated with the menu items added by the previous example. STDMETHODIMP CShellExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi) { HRESULT hr = E_INVALIDARG; // If the high-order word of lpcmi->lpVerb is not NULL, this // function was called by an application and lpVerb is a command // that should be activated. Otherwise, the shell has called this // function, and the low-order word of lpcmi->lpVerb is the // identifier of the menu item that the user selected. if (!HIWORD(lpcmi->lpVerb)) { switch (LOWORD(lpcmi->lpVerb)) { case 0: hr = DoMenu1(lpcmi->hwnd, lpcmi->lpDirectory, lpcmi->lpVerb, lpcmi->lpParameters, lpcmi->nShow); break; case 1: hr = DoMenu2(lpcmi->hwnd, lpcmi->lpDirectory, lpcmi->lpVerb, lpcmi->lpParameters, lpcmi->nShow); break; case 2: hr = DoMenu3(lpcmi->hwnd, lpcmi->lpDirectory, lpcmi->lpVerb, lpcmi->lpParameters, lpcmi->nShow); break; case 3: hr = DoMenu4(lpcmi->hwnd, lpcmi->lpDirectory, lpcmi->lpVerb, lpcmi->lpParameters, lpcmi->nShow); break; } } return hr; } Also ich halte das auch für etwas aufwendig, aber so wird´s halt scheinbar gemacht. Die Auszüge sind alle aus der M$ MSDN! Also frage mich nicht, was was genau bedeuten soll. Vielleicht bringt Dich aber das weiter. Du mußt hat alles über DLLMain oder DLLLibmain integrieren - das ist wohl die Absicht Deines "Chefs".
-
Also gestern habe ich mir mal wiederein paar Bücher angeschaut und mir ist dabei das Sybex-Bios-Buch aufgefallen (Vorsicht - es gibt nur ein richtig dickes aber wohl mehrere Dünnere) und nach dem was da alles drinstand würde ich behaupten ein Blick auf die richtige Seite oder den im Buch genannten Links könnte Dir Klarheit verschaffen. Halt mal bei einer brauchbaren Buchhandlung Ausschau danach und schreibe Dir die Links ab. Ich werde mir das 100DM Buch wohl noch zulegen, weil einfach alles wirklich gut erklärt ist. So kann man an der Hardware bis ins letzte Detail rumschrauben (von der Festplatte bis zum Joystick) ohne daß man sich das vom System "genehmigen" lassen muß - eigentlich eine positive Sache. Ich muß aber zugeben, daß das Auslesen vom Bios mir nicht ins Auge gesprungen ist, aber wie gesagt denke ich von Umfang und Komplexität des Buches, daß es hier sicher Antworten dazu gibt. Einige Interrupts sind jedoch vom Hersteller frei definierbar und können relativ stark voneinander abweichen und da hilft dann nur direkter Developer-Support (darauf wurde auch aufmerksam gemacht). Ich habe nur 10 Minuten rumgeblättert, aber ich denke ich werde mir das Teil in absehbarer Zeit ins Regal stellen. <FONT COLOR="#a62a2a" SIZE="1">[ 19. Oktober 2001 10:12: Beitrag 2 mal editiert, zuletzt von Crush ]</font>
-
Also ich bin mir da nicht ganz so sicher, weil ich´s nicht getestet hatte aber wahrscheinlich stimmt das schon... ich habe als Abschlußprüfung einen Oracle-Client (gedacht als ODBC-Alternative-Class für ein Produkt) erstellt. Mein "Chef"-Programmierer war oraclemäßig wirklich topfit und ich habe auch das ganze (ohne irgendwelche Zusatzanmeldungen zum Sperren oder ähnliches) für Multiuser (nicht direkt nur fürs Netz, sondern für mehrere User am selben Rechner, also mehrere mal kann das Programm parallel gestartet werden) erstellt - ich kam wegen dem Prüfungsstreß nicht mehr dazu das ganze tatsächlich ins Hauptprogramm zu implementieren, aber da das ein wichtiger Bestandteil der Klasse war und ich vor der Prüfung alles auf Funktionsfähigkeit allein im Debugger mit nem kleinem Testprogramm und mit dem Oracle-Mann logisch betrachtet durchging und der in keinster Weise diesem Multi-Instanz-Verfahren ohne DB-Sperrung oder ähnliches voll zustimmte gehe ich davon aus, daß das schon geht - man bekommt halt wohl eine Fehlermeldung, sollte ein Datensatz bearbeitet werden - auf jeden Fall beim Schreiben. Schlimmstenfalls würde sich Oracle die Vorgänge merken und nach der Reihenfolge der Anmeldung abarbeiten, das wäre auch noch korrekt. Leider ist nachher nix mehr draus geworden, weil man sich nach 2 Tagen harter Arbeit dafür entschied das ganze wegen der Beschleunigungs- und Optimiermöglichkeiten über OCI laufen zu lassen, also mußte ich alles nochmal von vorne schreiben, weil OCI komplett anders funktioniert (aber abgesehen davon die höchste Aktualisierung seitens Oracle hat) aber auch unvergleichlich schwieriger zu realisieren ist (um ehrlich zu sein nach der 1500-Seiten-Anleitung für die Programmierschnittstelle stand ich erst mal da wie der Ochs vorm Berg). Also rein von der Benutzung ist das wie das Steinrad vom Neandertaler (Oracle-ODBC & T-Net) im Vergleich zum Ferrari (OCI). Wenn Du mal jemand so richtig leiden lassen willst, oder mal testen willst, was DB-Programmierung noch so bedeuten kann, dann zieh Dir mal von der Oracle Developer-Page die OCI-Anleitung, vor allem deshalb, weil sich mit OCI praktisch kaum einer auskennt und nur wenig brauchbare Dokus existieren, aber Dich im DB-Bereich OCI-Kenntnisse zum Guru erleuchten. OCI ist übrigens ein Standard, der von fast allen Datenbanken (auf jeden Fall denen die was taugen) unterstützt wird. Aber um nochmal auf die Frage zurückzukommen: Eine gesonderte Behandlung auf parallele Transaktionen würde ich nur dann beim Server direkt nochmal implantieren, wenn es absolut unerläßlich ist herauszufinden, wer wann an der Datenbank rumgespielt hat. Das könnte man bestimmt auch in den Server-Logs irgendwie rausbekommen können, aber sollte das in einem extra Server-Programm benötigt werden, dann mußt Du halt die Abfragen nach gleichen Tabellen checken bevor sie an die Datenbank geschickt werden und diese gegebenenfalls direkt blockieren oder halt in eine "Warteschlange" setzen. Das würde aber bedeuten, daß die Kommunikation zu Datenbank auf ein Extraprogramm umgelenkt werden muß, welches halt für die Clients vor sich hinrödelt - und das wäre auch ein (relativ) enormer Aufwand für ein bestehendes Client-Programm und unnötiger Traffic würde verursacht. Ob das wirklich notwendig ist??? Was nicht unbedingt sein muß muß auch nicht programmiert werden, weil die Kunden nur dafür zahlen, was sie wirklich wollen und nicht für den 5. Airbag oder eine zusätzliche Kühlerskülptur aufkommen wollen. Immer im voruas schon Input-Output abwägen und nur dann Input zulassen, wenn der Output dafür auch garantiert ist! Im schlimmsten Fall muß man sich halt überlegen, ob die Clients voneinander wissen dürfen und die Sperrung selber miteinander ausmachen. Also ich würde das alles einfach der Datenbank überlassen - die kümmert sich schon drum (hat ja auch genug gekostet) und ein GAU ist nicht zu erwarten. Die Frage ist halt auch, wie das Programm auf eine Sperrung reagiert. Sollte da dann einfach eine Fehlermeldung kommen, ein Retry, oder halt erstmal gar nix? Da würde ich mir eher drüber Gedanken machen. Und es ist auch die Frage wann das bemerkbar wird: Beim Select oder erst beim Schreiben? Hier würde ich erstmal rumtesten und dann weitere Schritte überlegen. <FONT COLOR="#a62a2a" SIZE="1">[ 19. Oktober 2001 10:00: Beitrag 3 mal editiert, zuletzt von Crush ]</font>
-
Das mit der PS2 habe ich schon gesehen, aber ich dachte nicht, daß die Kiste das ganze so gut hinbekommen kann und dachte eher an gefakete Screenshots. Aber andererseits, wenn die PS2 heute das schon kann, dann kann der PC bis zum Erscheinungstermin des Spiels schon erfahrungsgemäßt mindestens das Doppelte! Wollte da nicht mal einer den Markt mit einem Realtime-Raytracing-Chip revolutionieren? Wird langsam zeit... <FONT COLOR="#a62a2a" SIZE="1">[ 19. Oktober 2001 09:20: Beitrag 1 mal editiert, zuletzt von Crush ]</font>
-
Wieso nicht einfach mit 1 anfgangen und mit 2 weitermachen. Das unnötige Versions-Gezeter ist doch nur bei echten Großprojekten wirklich sinnvoll.
-
ADO (ja die mit der Goldkante) gibts bei M$ genauso, nämlich als COM-Wrapper der OLE DB. Über ODBC läuft dann das ganze unter dem Namen RDO. Wichtig ist halt, daß im System-DSN (für alle Benutzer) oder Benutzer-DSN (für die entsprechende Anmeldung) die ODBC-Datenquelle richtig vordefiniert ist, dann geht ein Zugriff auf die Elemente recht unkompliziert vor sich -> siehe MSDN. Ein guter Buchtip für Win-Themen aller Art ist von Microsoft Press das "Microsoft Visual C++ 6 Programmierhandbuch" welches nämlich den Idealweg zu den gewünschten Lösungen mit allen Stolperfallen aufzeigt! <FONT COLOR="#a62a2a" SIZE="1">[ 18. Oktober 2001 22:11: Beitrag 1 mal editiert, zuletzt von Crush ]</font>
-
Irgendwie muß Borland auch damit funken, denn wenn man die zusätzlichen Links weiterverfolgt kommt man auf Sites, die Packages haben, mit denen man Zusatz-Libraries nutzen kann, wie z.B. Borland Database Engine oder Borland Gfx-Libraries ... also ich finde das schon genial. Irgendwo war eine Vollständige Version der Entwicklungsumgebung mit fertig installiertem Compiler. Man muß halt ein wenig weitersuchen und nicht gleich das erste Beste nehmen was man so findet. Es gibt auch noch ein Konfigurierungsprogramm für das Teil als Extra irgendwo, damit werden auch die Packages direkt in die Umgebung reingefügt. Achtung! Es gibt verschiedene Versionen, doch nur eine ist für Win32, alles andere ist Linux oder sonstwas. NICHT AUFGEBEN! ES LOHNT SICH! <FONT COLOR="#a62a2a" SIZE="1">[ 18. Oktober 2001 21:46: Beitrag 1 mal editiert, zuletzt von Crush ]</font>
-
Lecker! Erinnert mich ein wenig an ein paar Szenen aus "Bad Taste".
-
Also es ist immer einfacher vom Höheren auf das Niedrigere zu blicken, weil dann halt nicht mehr viel neues dazukommt. Das bedeutet nicht, daß Java schlechter wäre - es ist halt in der Syntax C++ gegenüber sagen wir mal "eingeschränkt". Wie gesagt fehlen auch einige Sprachbestandteile, wodurch Java zwar übersichtlicher aber doch limitierter einsetzbar ist als C++. Grundsätzlich kann man fast alle "normalen" Anwendungen in beiden Sprachen realisieren, allerdings hat man halt bei C++ eine wesentlich größere Code-Basis auf die man zugreifen kann und der direkte Hardware-Port steht einem offen (obwohl man ja immer mehr vom Direkten ins Indirekte abrutscht - halt Kapselung und Wiedervewendung von standardisierten Schnittstellen). C# soll übrigens ein angenehmer Mittelsmann zwischen C++ und Java werden, mal schauen was draus wird. Die Reihenfolge ob C++ oder Java zu lernen ist wohl eher eine Frage des persönlichen Geschmacks. Ich halte beide Wege für gleichwertig. Noch ist es aber so, daß C++-Programmierern einfach mehr Insider-Kenntnisse zugesprochen werden - weil halt bei Java alles innerhalb einer VM läuft. Kann man beides, ist man für die Industrie bestens gerüstet. Sagen wir mal 90-95% Java sind in C++ enthalten (eigentlich hat SUN ja vom Design her Java auch von C++ abgekupfert). Man muß allerdings bei jeder Programmiersprache sich schon im Voraus Gedanken machen, auf welche Schiene man sich spezialisieren will: Hardware (Microcontroller), Internet, Benutzer-Oberflächen, DB-Anwendungen, (3D-)Spiele, Tools, Emulationen, System-Wrapper, BS-Konvertierungen, Betriebssysteme, Simulationen, usw.) je nachdem ist halt das eine dem anderen eventuell vorzuziehen. <FONT COLOR="#a62a2a" SIZE="1">[ 17. Oktober 2001 10:12: Beitrag 5 mal editiert, zuletzt von Crush ]</font>
-
Also ich kann mich erinnern mal gelesen zu haben, daß es Ausbildungsstätten geben soll, die wirklich Fachinformatiker mit zusätzlicher Fachhochschulreife ausbilden, jedoch ist die Ausbildung wesentlich härter, weil einfach mehr Fächer dann dazu kommen müssen (Mathematik, Physik, etc. war jedenfalls bei mir Voraussetzung für die FH-Reife). Ich habe FH und habe die Ausbildung zum FIAE hinter mir und ich muß sagen: Die FH macht sich wohl höchstens bei einer Bewerbung gut, weil man halt weiß, daß man auf ABI-Niveau vom Wissensstand ungefähr einzustufen ist. Man hat die Möglichkeit auch noch sich zum Wirtschaftsinformatiker, Bioinformatiker oder noch ein paar von den Exoten (Neuroinformatiker oder sowas in der Art gibt´s glaub auch) fortzubilden, wenn man den FI & FH hat. Allerdings da muß man dann selber für die Ausbildung löhnen sofern ich weiß. Vielleicht bilden aber auch Firmen für Eigenbedarf in dieser Richtung aus. Würde mich auch interessieren, wie man theoretisch noch weitermachen könnte, sofern man nach der FI-Ausbildung jedoch nicht eine höhere Bildung anstrebt ist sie unnütz.
-
Benutzeroberfläche? Der war nur ein Kommandozeilen-Compiler, am besten sowas wie das hier mit benutzen: http://www.downlinx.com/proghtml/63/6397.htm Aber ich empfehle Dir vieeeel lieber das hier zu benutzen, falls Du Visual Studio gut findest: DEV-C++ http://www.bloodshed.net/ oder http://sourceforge.net/projects/dev-cpp/ Das Ding ist der absolute Hammer als Entwicklungsumgebung - und absolut kostenlos! Ich bin mir nicht sicher, aber vielleicht kannst Du sogar den Borland C++-Compiler einbinden, probier halt mal rum. Irgendwo muß da die Windows-Version sein. Übrigens: Allen weiteren Links folgen und Packages für BorlandGFX, DirectX, OpenGL und vieles mehr mit Packageupdater runterziehen, dann macht das ganze erst richtig Spaß! Auch der Source ist erhältlich, sodaß Delphi Coder das Ding eigenständig nach Bedürfnissen erweitern können. Eigentlich ist das das Beste was ich auf Freeware-Basis kenne. <FONT COLOR="#a62a2a" SIZE="1">[ 16. Oktober 2001 21:44: Beitrag 3 mal editiert, zuletzt von Crush ]</font>