DebugWindow bruker Atoms

Forklarer hva Atomer er og hvordan du kan bruke dem til å sende strenger til andre programmer - uten behov for delt memory.Topic: DebugWindow bruker Atomer og MessagesAreas: Windows API, komponent utvikling, AtomsAuthor: John Scalco, April 01, 2001 , mailto: [email protected] merk: for en html-versjon av denne artikkelen og /eller kildekoden, kan du laste ned koden fra http://www.idealsw.com/filedownloads.htmlA lenge siden i en langt utenfor 16-bit Galaxy, var jeg bruker Delphi 1.0. På den tiden jobbet jeg på et program, som gjorde kommunikasjon i sanntid. Delphi 1.0 debugger var en C dll, som (i mitt tilfelle) ofte fikk skadet hvis jeg setter stoppunkter i visse funksjoner. Som et resultat, virket det som jeg har brukt mye tid på å restarte PC-en min - som Windows 3.1 ville ikke slippe dll som debugger var using.In tillegg for min søknad ved å plassere stoppunkter i koden jeg kjører risikoen for at jeg kan endre måten programmet jobbet (det var en kommunikasjons type programvare pakken) etter en stund og mange reboots senere, jeg ble lei av det, og jeg fant meg selv å tenke, "Jøss, jeg skulle ønske jeg hadde en feilsøkingsvinduet som Visual C ++ og Visual Basic ha ". Selv, er bruk av Visual C ++ 's feilsøkingsvinduet et godt utgangspunkt funksjonen klok, jeg trengte flere funksjoner enn det som tilbys. Hvis bare Delphi hadde noe sånt. Jeg ønsket følgende funksjoner: Evne til å se data i "Viewer" mens programmet var running.The Mulighet for å lagre disse dataene til en fil, skrive den til en fil, og skriv inn teksten til å legge ekstra annotations.I ønsket også å tillate brukeren av produktet mitt til å kjøre dette verktøyet (på sin pc) til å utføre feilsøking "ute i felten" .Nå someo av dere kan si "hei hvorfor ikke bruke Hendelsesliste ??" ... God idé, men det var ikke tilgjengelig i Win16, og det fortsatt ikke har alle funksjonene jeg har nevnt ovenfor ... spesielt at den kunne brukes av en kunde ut i field.With Delphi, jeg lett kunne få de fleste av disse funksjonene ved å skrive et frittstående program med Memo komponent i det og noen ekstra kode. Problemet var å få utgang fra min søknad til den andre application.Enter Windows SDK. Jeg vet det kan høres vridd, men jeg noen ganger Snoop SDK for interessante funksjoner, vel en dag mens jeg var "snusing", kom jeg over noe som kalles en Atom.An Atom lar deg plassere en streng på et sted i OS der hvem som helst kan få tilgang til det uavhengig av hva prosessen du er i. det er som delt minne, men du trenger ikke gjøre mye arbeid for å tillate andre prosesser for å få på data.In for å få tilgang til atom du må vite hva den "nøkkelen" er å hente data i Atom. Så lenge alle programmer "vet" hva nøkkelen er, kan det hente data fra Atom.Using dette Atom, kunne jeg plassere strengen i minnet, og da kunne jeg la min andre programmet "vite" at jeg hadde satt den informasjonen der og deretter app kan hente den og vise it.It kan gjøre det lettere å tenke på dette som en klient /server forhold. Kunden er programmet, som blir feilsøkt. Server er programmet eller betrakteren, som vil ha ansvar for å vise meldingen. Dette åpner opp noen interessante muligheter: Tenk deg at du ønsket å filtrere meldinger eller utføre andre typer handlinger basert på bestemte meldinger som print en message.So, klienten trenger å gjøre følgende: Sett streng beskjed i et atom. For eksempel, 'Hello World' andSend en melding til Server-programmet som indikerer at strengen er tilgjengelig for lesing. Serveren må gjøre følgende: Handle meldingen (Windows Message), noe som indikerer strengen er tilgjengelig for lesing og trekke strengen fra Atom vise det i debug betrakteren. Her er Kundens kode. Jeg bestemte meg for å plassere denne i en prosedyre slik at jeg ikke måtte gjenta den samme koden hver gang jeg ønsket å legge en debug message.procedure DebugMsg (AMsg: string); Var szMsg: array [0..255] av røye; Atom: TAtom; begynne //Legg et atom listen over globale atomer //tilgjengelig fra alle programmer Atom: = GlobalAddAtom (StrPCopy (szMsg, AMsg)); //Kringkaste melding om at jeg har //oppdatert min atom til alle topp vinduer - Jeg vet ikke //hvilket vindu er et feilsøkingsvinduet. Sendmessage (hwnd_broadcast, wm_DebugId, 0, Atom); //Slette atom - etter den tid //meldingen er sendt over, blir //atom ikke lenger nødvendig //- i teorien :) GlobalDeleteAtom (Atom); end; The Atom legges til den globale listen over Atomer - som er tilgjengelig med alle programmer - så lenge de vet at 'key'. Forresten, størrelsen på strengen, i henhold til docs, er begrenset til 255; Selv om dette høres ut som Win16 docs ... kanskje noen har glemt å oppdatere dem ?? Deretter sendes en melding til alle topp vinduer - det er (stort sett) alle programmer som kjører. Snarere enn å måtte vite navnet på programmet, som kjører debug betrakteren, jeg bare sende meldingen til alle topp vinduer. Dette holder våre muligheter åpne - kanskje på et tidspunkt, kan jeg skrive en debug seer app? Denne måten jeg ikke trenger å endre koden i Client, jeg bare nødt til å gjennomføre en annen server som vet hva meldingen for å lytte til, og det kan også motta meldinger om debugging activity.As en påminnelse, funksjonen Sendmessage () vil ikke tilbake til den har sendt meldingen, så da neste linje er nådd, har Atom allerede blitt lest fra av "betrakte application.A siste merknad om dette kodebiten er budskapet, som jeg bruker wm_DebugId der gjør at komme fra??? Vel, Windows faktisk unikt genererer den. Det er mange meldinger i Windows, hvis du bare plukke en tilfeldig nummer, det er en sjanse for at det kan brukes til noe annet. For eksempel hva om du brukte meldingen, som endrer fargen på vinduet - du kan ha noen ganske "interessante resultater. Windows løser dette potensielle problemet ved å gi en API-kall, RegisterWindowMessage (), som lar deg lage (og reserve) en unik Windows message.procedure DebugMsg_Init, begynner WM_DebugId: = RegisterWindowMessage ( 'IS_Debug'); end; Dette budskapet må være opprettet før samtaler til DebugMsg () er gjort. Jeg gjør dette ved å plassere denne koden i initialisering delen av enheten der jeg har all min kode plassert. Plassere denne koden i initialisering delen av enheten garanterer at koden vil bli kalt når enheten er lastet inn i minnet ved starten av programmet, noe som resulterer i min egen melding blir registrert før eventuelle samtaler til DebugMsg () er made.Ok , så vi har en idé om hvordan du kan sende meldingen fra klientapplikasjonen til serveren. Nå la oss se på hva "Server" har å gjøre for å fange meldingen. Server CodeThe løsningen er å sette opp et vindu Proc og se etter at message.It ser omtrent slik ut: prosedyre TForm1.DefaultHandler (var Msg: TMessage); Var szBuffer: Array [0..255] av Char; sMsg: String; begynne //sjekke om det er den debug id. hvis Msg.Msg = GetDebugId deretter begynne hvis GlobalGetAtomName (Msg.LParam, szBuffer, 255) = 0, så StrCopy (szBuffer, 'Feil: Atom ikke funnet'); sMsg: = StrPas (szBuffer); Memo1.Lines.Add ( 'DBG > >' + sMsg); end, end, The DefaultHandler metoden faktisk håndterer meldinger som ikke håndteres av skjemaet. Så kan vi overstyre denne metoden, og legge til noen kode, som vil sjekke, for vår egen melding wm_debugId. Hvis vi får denne meldingen, vet vi at vi ønsker å håndtere det; ellers kan vi la alle andre meldinger pass through.Using Windows API GlobalGetAtomName (), jeg hente Atom fra Atom bordet og jeg deretter konvertere null terminert streng til en vanlig Pascal streng. Jeg så skriv det til Memo komponent, som er på form.To holde avhengigheter (og hardt koding) til et minimum, skrev jeg en funksjon som heter GetDebugId (), som returnerer hva WM_DebugID er angitt som, dette gjør at alle programmer som ønsker å vise meldinger fra betrakteren en måte å få de riktige WM_DebugId uten uhell endre det eller avhengig av hvordan den er implementert - ettersom funksjonen "omslutter" det er implementering og er i Unit kalt IS_Debug.pas.If du har lastet ned kildekoden for IS_Debug.pas, har du kanskje lagt merke til at jeg erklærte WM_DebugId som en variabel under gjennomføringen delen. Dette er ikke en mistake.Before dager Delphi (Turbo Pascal) hvis du ønsket å holde brukerne av en enhet får tilgang til visse typer data eller selv å vite hvordan type ble gjennomført, kan du sette erklæringer under gjennomføring delen, og det ville være privat til unit.Anything - inkludert funksjoner, metoder, klasser og så videre erklærte under gjennomføringen av enheten kan ikke nås av koden som bruker enheten. Så det er i utgangspunktet en privat variabel uten stedene. Her er det for fullstendighet: funksjon GetDebugId: integer; begynne Resultat: = WM_DebugId; ende, og der har du en fin måte å tillate et program å passere meldinger til andre programmer uten å måtte bruke delte memory.This lite verktøy har vært så nyttig jeg brukte den mange ganger, nå hendelseslisten er tilgjengelig, men du vet at jeg fortsatt liker denne tilnærmingen fordi jeg kan skrive den ut, kan jeg skrive inn det som notepad og jeg kan klippe og lime - pluss en kunde kan bruke den som en debug verktøy for å diagnostisere et problem. Så for å si det mildt for meg har det vært nyttig. Jeg viste dette til den lokale Delphi Interest Group her i Raleigh-Durham noen måneder tilbake, og alle syntes å like det. Noen sa "Hva med en komponent-versjonen?" Jeg hadde tenkt på dette, men fikk aldri rundt for å gjøre det ... før nå. Hvis du er interessert i en komponent versjon av denne, som du kan slippe inn i programmene, så les min kommende artikkel, som i utgangspunktet bygger på dette.Jeg håper du finner dette nyttig og kan du gjerne stille spørsmål du måtte ha om dette article.Sincerely, John ScalcoIdeal Software, Inc.Raleigh-Durham, NC 27502mailto: [email protected]: //www.idealsw.com



Previous:
Next Page: