Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915159161591715918159191592015921159221592315924159251592615927159281592915930159311593215933159341593515936159371593815939159401594115942159431594415945159461594715948159491595015951159521595315954159551595615957159581595915960159611596215963159641596515966159671596815969159701597115972159731597415975159761597715978159791598015981159821598315984159851598615987159881598915990159911599215993159941599515996159971599815999160001600116002160031600416005160061600716008160091601016011160121601316014160151601616017160181601916020160211602216023160241602516026160271602816029160301603116032160331603416035160361603716038160391604016041160421604316044160451604616047160481604916050160511605216053160541605516056160571605816059160601606116062160631606416065160661606716068160691607016071160721607316074160751607616077160781607916080160811608216083160841608516086160871608816089160901609116092160931609416095160961609716098160991610016101161021610316104161051610616107161081610916110161111611216113161141611516116161171611816119161201612116122161231612416125161261612716128161291613016131161321613316134161351613616137161381613916140161411614216143161441614516146161471614816149161501615116152161531615416155161561615716158161591616016161161621616316164161651616616167161681616916170161711617216173161741617516176161771617816179161801618116182161831618416185161861618716188161891619016191161921619316194161951619616197161981619916200162011620216203162041620516206162071620816209162101621116212162131621416215162161621716218162191622016221162221622316224162251622616227162281622916230162311623216233162341623516236162371623816239162401624116242162431624416245162461624716248162491625016251162521625316254162551625616257162581625916260162611626216263162641626516266162671626816269162701627116272162731627416275162761627716278162791628016281162821628316284162851628616287162881628916290162911629216293162941629516296162971629816299163001630116302163031630416305163061630716308163091631016311163121631316314163151631616317163181631916320163211632216323163241632516326163271632816329163301633116332163331633416335163361633716338163391634016341163421634316344163451634616347163481634916350163511635216353163541635516356163571635816359163601636116362163631636416365163661636716368163691637016371163721637316374163751637616377163781637916380163811638216383163841638516386163871638816389163901639116392163931639416395163961639716398163991640016401164021640316404164051640616407164081640916410164111641216413164141641516416164171641816419164201642116422164231642416425164261642716428164291643016431164321643316434164351643616437164381643916440164411644216443164441644516446164471644816449164501645116452164531645416455164561645716458164591646016461164621646316464164651646616467164681646916470164711647216473164741647516476164771647816479164801648116482164831648416485164861648716488164891649016491164921649316494164951649616497164981649916500165011650216503165041650516506165071650816509165101651116512165131651416515165161651716518165191652016521165221652316524165251652616527165281652916530165311653216533165341653516536165371653816539165401654116542165431654416545165461654716548165491655016551165521655316554165551655616557165581655916560165611656216563165641656516566165671656816569165701657116572165731657416575165761657716578165791658016581165821658316584165851658616587165881658916590165911659216593165941659516596165971659816599166001660116602166031660416605166061660716608166091661016611166121661316614166151661616617166181661916620166211662216623166241662516626166271662816629166301663116632166331663416635166361663716638166391664016641166421664316644166451664616647166481664916650166511665216653166541665516656166571665816659166601666116662166631666416665166661666716668166691667016671166721667316674166751667616677166781667916680166811668216683166841668516686166871668816689166901669116692166931669416695166961669716698166991670016701167021670316704167051670616707167081670916710167111671216713167141671516716167171671816719167201672116722167231672416725167261672716728167291673016731167321673316734167351673616737167381673916740167411674216743167441674516746167471674816749167501675116752167531675416755167561675716758167591676016761167621676316764167651676616767167681676916770167711677216773167741677516776167771677816779167801678116782167831678416785167861678716788167891679016791167921679316794167951679616797167981679916800168011680216803168041680516806168071680816809168101681116812168131681416815168161681716818168191682016821168221682316824168251682616827168281682916830168311683216833168341683516836168371683816839168401684116842168431684416845168461684716848168491685016851168521685316854168551685616857168581685916860168611686216863168641686516866168671686816869168701687116872168731687416875168761687716878168791688016881168821688316884168851688616887168881688916890168911689216893168941689516896168971689816899169001690116902169031690416905169061690716908169091691016911169121691316914169151691616917169181691916920169211692216923169241692516926169271692816929169301693116932169331693416935169361693716938169391694016941169421694316944169451694616947169481694916950169511695216953169541695516956169571695816959169601696116962169631696416965169661696716968169691697016971169721697316974169751697616977169781697916980169811698216983169841698516986169871698816989169901699116992169931699416995169961699716998169991700017001170021700317004170051700617007170081700917010170111701217013170141701517016170171701817019170201702117022170231702417025170261702717028170291703017031170321703317034170351703617037170381703917040170411704217043170441704517046170471704817049170501705117052170531705417055170561705717058170591706017061170621706317064170651706617067170681706917070170711707217073170741707517076170771707817079170801708117082170831708417085170861708717088170891709017091170921709317094170951709617097170981709917100171011710217103171041710517106171071710817109171101711117112171131711417115171161711717118171191712017121171221712317124171251712617127171281712917130171311713217133171341713517136171371713817139171401714117142171431714417145171461714717148171491715017151171521715317154171551715617157171581715917160171611716217163171641716517166171671716817169171701717117172171731717417175171761717717178171791718017181171821718317184171851718617187171881718917190171911719217193171941719517196171971719817199172001720117202172031720417205172061720717208172091721017211172121721317214172151721617217172181721917220172211722217223172241722517226172271722817229172301723117232172331723417235172361723717238172391724017241172421724317244172451724617247172481724917250172511725217253172541725517256172571725817259172601726117262172631726417265172661726717268172691727017271172721727317274172751727617277172781727917280172811728217283172841728517286172871728817289172901729117292172931729417295172961729717298172991730017301173021730317304173051730617307173081730917310173111731217313173141731517316173171731817319173201732117322173231732417325173261732717328173291733017331173321733317334173351733617337173381733917340173411734217343173441734517346173471734817349173501735117352173531735417355173561735717358173591736017361173621736317364173651736617367173681736917370173711737217373173741737517376173771737817379173801738117382173831738417385173861738717388173891739017391173921739317394173951739617397173981739917400174011740217403174041740517406174071740817409174101741117412174131741417415174161741717418174191742017421174221742317424174251742617427174281742917430174311743217433174341743517436174371743817439174401744117442174431744417445174461744717448174491745017451174521745317454174551745617457174581745917460174611746217463174641746517466174671746817469174701747117472174731747417475174761747717478174791748017481174821748317484174851748617487174881748917490174911749217493174941749517496174971749817499175001750117502175031750417505175061750717508175091751017511175121751317514175151751617517175181751917520175211752217523175241752517526175271752817529175301753117532175331753417535175361753717538175391754017541175421754317544175451754617547175481754917550175511755217553175541755517556175571755817559175601756117562175631756417565175661756717568175691757017571175721757317574175751757617577175781757917580175811758217583175841758517586175871758817589175901759117592175931759417595175961759717598175991760017601176021760317604176051760617607176081760917610176111761217613176141761517616176171761817619176201762117622176231762417625176261762717628176291763017631176321763317634176351763617637176381763917640176411764217643176441764517646176471764817649176501765117652176531765417655176561765717658176591766017661176621766317664176651766617667176681766917670176711767217673176741767517676176771767817679176801768117682176831768417685176861768717688176891769017691176921769317694176951769617697176981769917700177011770217703177041770517706177071770817709177101771117712177131771417715177161771717718177191772017721177221772317724177251772617727177281772917730177311773217733177341773517736177371773817739177401774117742177431774417745177461774717748177491775017751177521775317754177551775617757177581775917760177611776217763177641776517766177671776817769177701777117772177731777417775177761777717778177791778017781177821778317784177851778617787177881778917790177911779217793177941779517796177971779817799178001780117802178031780417805178061780717808178091781017811178121781317814178151781617817178181781917820178211782217823178241782517826178271782817829178301783117832178331783417835178361783717838178391784017841178421784317844178451784617847178481784917850178511785217853178541785517856178571785817859178601786117862178631786417865178661786717868178691787017871178721787317874178751787617877178781787917880178811788217883178841788517886178871788817889178901789117892178931789417895178961789717898178991790017901179021790317904179051790617907179081790917910179111791217913179141791517916179171791817919179201792117922179231792417925179261792717928179291793017931179321793317934179351793617937179381793917940179411794217943179441794517946179471794817949179501795117952179531795417955179561795717958179591796017961179621796317964179651796617967179681796917970179711797217973179741797517976179771797817979179801798117982179831798417985179861798717988179891799017991179921799317994179951799617997179981799918000180011800218003180041800518006180071800818009180101801118012180131801418015180161801718018180191802018021180221802318024180251802618027180281802918030180311803218033180341803518036180371803818039180401804118042180431804418045180461804718048180491805018051180521805318054180551805618057180581805918060180611806218063180641806518066180671806818069180701807118072180731807418075180761807718078180791808018081180821808318084180851808618087180881808918090180911809218093180941809518096180971809818099181001810118102181031810418105181061810718108181091811018111181121811318114181151811618117181181811918120181211812218123181241812518126181271812818129181301813118132181331813418135181361813718138181391814018141181421814318144181451814618147181481814918150181511815218153181541815518156181571815818159181601816118162181631816418165181661816718168181691817018171181721817318174181751817618177181781817918180181811818218183181841818518186181871818818189181901819118192181931819418195181961819718198181991820018201182021820318204182051820618207182081820918210182111821218213182141821518216182171821818219182201822118222182231822418225182261822718228182291823018231182321823318234182351823618237182381823918240182411824218243182441824518246182471824818249182501825118252182531825418255182561825718258182591826018261182621826318264182651826618267182681826918270182711827218273/* * Unit tests for window message handling * * Copyright 1999 Ove Kaaven * Copyright 2003 Dimitrie O. Paun * Copyright 2004,2005,2016 Dmitry Timoshkov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
#include <assert.h>#include <limits.h>#include <stdarg.h>#include <stdio.h>
#include "windef.h"#include "winbase.h"#include "wingdi.h"#include "winuser.h"#include "winnls.h"#include "dbt.h"
#include "wine/test.h"
#define MDI_FIRST_CHILD_ID 2004
/* undocumented SWP flags - from SDK 3.1 */#define SWP_NOCLIENTSIZE 0x0800#define SWP_NOCLIENTMOVE 0x1000#define SWP_STATECHANGED 0x8000
#define SW_NORMALNA 0xCC /* undoc. flag in MinMaximize */
#ifndef WM_KEYF1#define WM_KEYF1 0x004d#endif
#ifndef WM_SYSTIMER#define WM_SYSTIMER 0x0118#endif
#define WND_PARENT_ID 1#define WND_POPUP_ID 2#define WND_CHILD_ID 3
#ifndef WM_LBTRACKPOINT#define WM_LBTRACKPOINT 0x0131#endif
#ifdef __i386__#define ARCH "x86"#elif defined __x86_64__#define ARCH "amd64"#elif defined __arm__#define ARCH "arm"#elif defined __aarch64__#define ARCH "arm64"#else#define ARCH "none"#endif
static BOOL (WINAPI *pActivateActCtx)(HANDLE,ULONG_PTR*);static HANDLE (WINAPI *pCreateActCtxW)(PCACTCTXW);static BOOL (WINAPI *pDeactivateActCtx)(DWORD,ULONG_PTR);static BOOL (WINAPI *pGetCurrentActCtx)(HANDLE *);static BOOL (WINAPI *pQueryActCtxW)(DWORD,HANDLE,void*,ULONG,void*,SIZE_T,SIZE_T*);static void (WINAPI *pReleaseActCtx)(HANDLE);
/* encoded DRAWITEMSTRUCT into an LPARAM */typedef struct{ union { struct { UINT type : 4; /* ODT_* flags */ UINT ctl_id : 4; /* Control ID */ UINT item_id : 4; /* Menu item ID */ UINT action : 4; /* ODA_* flags */ UINT state : 16; /* ODS_* flags */ } item; LPARAM lp; } u;} DRAW_ITEM_STRUCT;
/* encoded MEASUREITEMSTRUCT into a WPARAM */typedef struct{ union { struct { UINT CtlType : 4; UINT CtlID : 4; UINT itemID : 4; UINT wParam : 20; } item; WPARAM wp; } u;} MEASURE_ITEM_STRUCT;
static BOOL test_DestroyWindow_flag;static BOOL test_context_menu;static HWINEVENTHOOK hEvent_hook;static HHOOK hKBD_hook;static HHOOK hCBT_hook;static DWORD cbt_hook_thread_id;
static const WCHAR testWindowClassW[] ={ 'T','e','s','t','W','i','n','d','o','w','C','l','a','s','s','W',0 };
static LRESULT WINAPI ParentMsgCheckProcA(HWND, UINT, WPARAM, LPARAM);
/*FIXME: add tests for theseWindow Edge Styles (Win31/Win95/98 look), in order of precedence: WS_EX_DLGMODALFRAME: double border, WS_CAPTION allowed WS_THICKFRAME: thick border WS_DLGFRAME: double border, WS_CAPTION not allowed (but possibly shown anyway) WS_BORDER (default for overlapped windows): single black border none (default for child (and popup?) windows): no border*/
typedef enum { sent=0x1, posted=0x2, parent=0x4, wparam=0x8, lparam=0x10, defwinproc=0x20, beginpaint=0x40, optional=0x80, hook=0x100, winevent_hook=0x200, kbd_hook=0x400} msg_flags_t;
struct message { UINT message; /* the WM_* code */ msg_flags_t flags; /* message props */ WPARAM wParam; /* expected value of wParam */ LPARAM lParam; /* expected value of lParam */ WPARAM wp_mask; /* mask for wParam checks */ LPARAM lp_mask; /* mask for lParam checks */};
struct recvd_message { UINT message; /* the WM_* code */ msg_flags_t flags; /* message props */ HWND hwnd; /* window that received the message */ WPARAM wParam; /* expected value of wParam */ LPARAM lParam; /* expected value of lParam */ int line; /* source line where logged */ const char *descr; /* description for trace output */ char output[512]; /* trace output */};
/* Empty message sequence */static const struct message WmEmptySeq[] ={ { 0 }};/* CreateWindow (for overlapped window, not initially visible) (16/32) */static const struct message WmCreateOverlappedSeq[] = { { HCBT_CREATEWND, hook }, { WM_GETMINMAXINFO, sent }, { WM_NCCREATE, sent }, { WM_NCCALCSIZE, sent|wparam, 0 }, { 0x0093, sent|defwinproc|optional }, { 0x0094, sent|defwinproc|optional }, { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, { WM_CREATE, sent }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, { 0 }};/* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE) * for a not visible overlapped window. */static const struct message WmSWP_ShowOverlappedSeq[] = { { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { WM_NCPAINT, sent|wparam|optional, 1 }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent|optional }, { HCBT_ACTIVATE, hook }, { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, { WM_NOTIFYFORMAT, sent|optional }, { WM_QUERYUISTATE, sent|optional }, { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* Win9x: SWP_NOSENDCHANGING */ { WM_ACTIVATEAPP, sent|wparam, 1 }, { WM_NCACTIVATE, sent }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ACTIVATE, sent|wparam, 1 }, { HCBT_SETFOCUS, hook }, { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, { WM_GETTEXT, sent|optional }, { WM_NCPAINT, sent|wparam|optional, 1 }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent|optional }, /* Win9x adds SWP_NOZORDER below */ { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { WM_GETTEXT, sent|optional }, { WM_NCCALCSIZE, sent|wparam|optional, 1 }, { WM_NCPAINT, sent|wparam|optional, 1 }, { WM_ERASEBKGND, sent|optional }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SYNCPAINT, sent|optional }, { WM_GETTITLEBARINFOEX, sent|optional }, { WM_PAINT, sent|optional }, { WM_NCPAINT, sent|beginpaint|optional }, { WM_GETTEXT, sent|beginpaint|defwinproc|optional }, { WM_ERASEBKGND, sent|beginpaint|optional }, { 0 }};/* SetWindowPos(SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE) * for a visible overlapped window. */static const struct message WmSWP_HideOverlappedSeq[] = { { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, { HCBT_ACTIVATE, hook|optional }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, { WM_ACTIVATEAPP, sent|wparam|optional, 1 }, { WM_NCACTIVATE, sent|optional }, { WM_ACTIVATE, sent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { 0 }};
/* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE) * for a visible overlapped window. */static const struct message WmSWP_ResizeSeq[] = { { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE }, { WM_GETMINMAXINFO, sent|defwinproc }, { WM_NCCALCSIZE, sent|wparam|optional, TRUE }, { WM_NCPAINT, sent|optional }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOCLIENTMOVE }, { WM_SIZE, sent|defwinproc|optional }, { WM_NCCALCSIZE, sent|wparam|optional, TRUE }, { WM_NCPAINT, sent|optional }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent|optional }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP sends a duplicate */ { 0 }};
/* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE) * for a visible popup window. */static const struct message WmSWP_ResizePopupSeq[] = { { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE }, { WM_GETMINMAXINFO, sent|defwinproc|optional }, /* Win9x */ { WM_NCCALCSIZE, sent|wparam|optional, TRUE }, { WM_NCPAINT, sent|optional }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOCLIENTMOVE }, { WM_SIZE, sent|defwinproc|wparam|optional, SIZE_RESTORED }, { WM_NCCALCSIZE, sent|wparam|optional, TRUE }, { WM_NCPAINT, sent|optional }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent|optional }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { 0 }};
/* SetWindowPos(SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE) * for a visible overlapped window. */static const struct message WmSWP_MoveSeq[] = { { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOSIZE }, { WM_NCPAINT, sent|optional }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOCLIENTSIZE }, { WM_MOVE, sent|defwinproc|wparam, 0 }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { 0 }};/* Resize with SetWindowPos(SWP_NOZORDER) * for a visible overlapped window * SWP_NOZORDER is stripped by the logging code */static const struct message WmSWP_ResizeNoZOrder[] = { { WM_WINDOWPOSCHANGING, sent|wparam, /*SWP_NOZORDER|*/SWP_NOACTIVATE }, { WM_GETMINMAXINFO, sent|defwinproc }, { WM_NCCALCSIZE, sent|wparam|optional, 1 }, { WM_NCPAINT, sent|optional }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam|optional, /*SWP_NOZORDER|*/SWP_NOACTIVATE, 0, SWP_NOMOVE|SWP_NOCLIENTMOVE|SWP_NOSIZE|SWP_NOCLIENTSIZE }, { WM_MOVE, sent|defwinproc|optional }, { WM_SIZE, sent|defwinproc|optional }, { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* Win9x doesn't send it */ { WM_NCPAINT, sent|optional }, /* Win9x doesn't send it */ { WM_GETTEXT, sent|defwinproc|optional }, /* Win9x doesn't send it */ { WM_ERASEBKGND, sent|optional }, /* Win9x doesn't send it */ { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { 0 }};
/* Switch visible mdi children */static const struct message WmSwitchChild[] = { /* Switch MDI child */ { WM_MDIACTIVATE, sent },/* in the MDI client */ { WM_WINDOWPOSCHANGING, sent|wparam,SWP_NOSIZE|SWP_NOMOVE },/* in the 1st MDI child */ { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_CHILDACTIVATE, sent },/* in the 1st MDI child */ /* Deactivate 2nd MDI child */ { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 2nd MDI child */ { WM_MDIACTIVATE, sent|defwinproc }, /* in the 2nd MDI child */ { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, /* Preparing for maximize and maximize the 1st MDI child */ { WM_GETMINMAXINFO, sent|defwinproc }, /* in the 1st MDI child */ { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_STATECHANGED }, /* in the 1st MDI child */ { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 }, /* in the 1st MDI child */ { WM_CHILDACTIVATE, sent|defwinproc }, /* in the 1st MDI child */ { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, /* in the 1st MDI child */ { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, /* in the 1st MDI child */ /* Lock redraw 2nd MDI child */ { WM_SETREDRAW, sent|wparam|defwinproc, 0 }, /* in the 2nd MDI child */ { HCBT_MINMAX, hook|lparam, 0, SW_NORMALNA }, /* Restore 2nd MDI child */ { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_STATECHANGED },/* in the 2nd MDI child */ { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },/* in the 2nd MDI child */ { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, /* in the 2nd MDI child */ { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, /* in the 2nd MDI child */ { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, /* in the 2nd MDI child */ { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* in the 2nd MDI child */ /* Redraw 2nd MDI child */ { WM_SETREDRAW, sent|wparam|defwinproc, 1 },/* in the 2nd MDI child */ /* Redraw MDI frame */ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE },/* in MDI frame */ { WM_NCCALCSIZE, sent|wparam, 1 },/* in MDI frame */ { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE}, /* in MDI frame */ { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* in MDI frame */ { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* in the 1st MDI child */ { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, /* in the 1st MDI child */ { WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, /* in the 1st MDI child */ { HCBT_SETFOCUS, hook }, { WM_KILLFOCUS, sent|defwinproc }, /* in the 2nd MDI child */ { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 },/* in the 1st MDI child */ { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent },/* in the MDI client */ { HCBT_SETFOCUS, hook }, { WM_KILLFOCUS, sent },/* in the MDI client */ { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, /* in the 1st MDI child */ { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|defwinproc }, /* in the 1st MDI child */ { WM_MDIACTIVATE, sent|defwinproc },/* in the 1st MDI child */ { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, /* in the 1st MDI child */ { 0 }};
/* Switch visible not maximized mdi children */static const struct message WmSwitchNotMaximizedChild[] = { /* Switch not maximized MDI child */ { WM_MDIACTIVATE, sent },/* in the MDI client */ { WM_WINDOWPOSCHANGING, sent|wparam,SWP_NOSIZE|SWP_NOMOVE },/* in the 2nd MDI child */ { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_CHILDACTIVATE, sent },/* in the 2nd MDI child */ /* Deactivate 1st MDI child */ { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 1st MDI child */ { WM_MDIACTIVATE, sent|defwinproc }, /* in the 1st MDI child */ /* Activate 2nd MDI child */ { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE}, /* in the 2nd MDI child */ { WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, /* in the 2nd MDI child */ { HCBT_SETFOCUS, hook }, /* in the 1st MDI child */ { WM_KILLFOCUS, sent|defwinproc }, /* in the 1st MDI child */ { WM_IME_SETCONTEXT, sent|defwinproc|optional }, /* in the 1st MDI child */ { WM_IME_SETCONTEXT, sent|optional }, /* in the MDI client */ { WM_SETFOCUS, sent, 0 }, /* in the MDI client */ { HCBT_SETFOCUS, hook }, { WM_KILLFOCUS, sent }, /* in the MDI client */ { WM_IME_SETCONTEXT, sent|optional }, /* in the MDI client */ { WM_IME_SETCONTEXT, sent|defwinproc|optional }, /* in the 1st MDI child */ { WM_SETFOCUS, sent|defwinproc }, /* in the 2nd MDI child */ { WM_MDIACTIVATE, sent|defwinproc }, /* in the 2nd MDI child */ { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE}, /* in the 2nd MDI child */ { 0 }};
/* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE| SWP_NOZORDER|SWP_FRAMECHANGED) * for a visible overlapped window with WS_CLIPCHILDREN style set. */static const struct message WmSWP_FrameChanged_clip[] = { { WM_WINDOWPOSCHANGING, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED }, { WM_NCCALCSIZE, sent|wparam|parent, 1 }, { WM_NCPAINT, sent|parent|optional }, /* wparam != 1 */ { WM_GETTEXT, sent|parent|defwinproc|optional }, { WM_ERASEBKGND, sent|parent|optional }, /* FIXME: remove optional once Wine is fixed */ { WM_NCPAINT, sent }, /* wparam != 1 */ { WM_ERASEBKGND, sent }, { WM_WINDOWPOSCHANGED, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { WM_PAINT, sent }, { 0 }};/* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_DEFERERASE|SWP_NOACTIVATE| SWP_NOZORDER|SWP_FRAMECHANGED) * for a visible overlapped window. */static const struct message WmSWP_FrameChangedDeferErase[] = { { WM_WINDOWPOSCHANGING, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_DEFERERASE|SWP_NOACTIVATE|SWP_FRAMECHANGED }, { WM_NCCALCSIZE, sent|wparam|parent, 1 }, { WM_WINDOWPOSCHANGED, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_DEFERERASE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { WM_PAINT, sent|parent|optional }, { WM_NCPAINT, sent|beginpaint|parent|optional }, /* wparam != 1 */ { WM_GETTEXT, sent|beginpaint|parent|defwinproc|optional }, { WM_PAINT, sent }, { WM_NCPAINT, sent|beginpaint }, /* wparam != 1 */ { WM_ERASEBKGND, sent|beginpaint|optional }, { 0 }};
/* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE| SWP_NOZORDER|SWP_FRAMECHANGED) * for a visible overlapped window without WS_CLIPCHILDREN style set. */static const struct message WmSWP_FrameChanged_noclip[] = { { WM_WINDOWPOSCHANGING, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED }, { WM_NCCALCSIZE, sent|wparam|parent, 1 }, { WM_NCPAINT, sent|parent|optional }, /* wparam != 1 */ { WM_GETTEXT, sent|parent|defwinproc|optional }, { WM_ERASEBKGND, sent|parent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { WM_PAINT, sent }, { WM_NCPAINT, sent|beginpaint }, /* wparam != 1 */ { WM_ERASEBKGND, sent|beginpaint|optional }, { 0 }};
/* ShowWindow(SW_SHOW) for a not visible overlapped window */static const struct message WmShowOverlappedSeq[] = { { WM_SHOWWINDOW, sent|wparam, 1 }, { WM_NCPAINT, sent|wparam|optional, 1 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { WM_NCPAINT, sent|wparam|optional, 1 }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent|optional }, { HCBT_ACTIVATE, hook|optional }, { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, { WM_NCPAINT, sent|wparam|optional, 1 }, { WM_ACTIVATEAPP, sent|wparam|optional, 1 }, { WM_NCACTIVATE, sent|wparam|optional, 1 }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ACTIVATE, sent|wparam|optional, 1 }, { HCBT_SETFOCUS, hook|optional }, { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|wparam|defwinproc|optional, 0 }, { WM_GETTEXT, sent|optional }, { WM_NCPAINT, sent|wparam|optional, 1 }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent|optional }, /* Win9x adds SWP_NOZORDER below */ { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { WM_NCCALCSIZE, sent|optional }, { WM_GETTEXT, sent|optional }, { WM_NCPAINT, sent|optional }, { WM_ERASEBKGND, sent|optional }, { WM_SYNCPAINT, sent|optional },#if 0 /* CreateWindow/ShowWindow(SW_SHOW) also generates WM_SIZE/WM_MOVE * messages. Does that mean that CreateWindow doesn't set initial * window dimensions for overlapped windows? */ { WM_SIZE, sent }, { WM_MOVE, sent },#endif { WM_PAINT, sent|optional }, { WM_NCPAINT, sent|beginpaint|optional }, { 0 }};/* ShowWindow(SW_SHOWMAXIMIZED) for a not visible overlapped window */static const struct message WmShowMaxOverlappedSeq[] = { { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, { WM_GETMINMAXINFO, sent }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_STATECHANGED }, { WM_GETMINMAXINFO, sent|defwinproc }, { WM_NCCALCSIZE, sent|wparam, TRUE }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { HCBT_ACTIVATE, hook|optional }, { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, { WM_ACTIVATEAPP, sent|wparam|optional, 1 }, { WM_NCACTIVATE, sent|wparam|optional, 1 }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ACTIVATE, sent|wparam|optional, 1 }, { HCBT_SETFOCUS, hook|optional }, { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|wparam|defwinproc|optional, 0 }, { WM_GETTEXT, sent|optional }, { WM_NCPAINT, sent|wparam|optional, 1 }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent|optional }, /* Win9x adds SWP_NOZORDER below */ { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_STATECHANGED }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, { WM_GETTEXT, sent|optional }, { WM_NCCALCSIZE, sent|optional }, { WM_NCPAINT, sent|optional }, { WM_ERASEBKGND, sent|optional }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SYNCPAINT, sent|optional }, { WM_GETTITLEBARINFOEX, sent|optional }, { WM_PAINT, sent|optional }, { WM_NCPAINT, sent|beginpaint|optional }, { WM_ERASEBKGND, sent|beginpaint|optional }, { 0 }};/* ShowWindow(SW_RESTORE) for a not visible maximized overlapped window */static const struct message WmShowRestoreMaxOverlappedSeq[] = { { HCBT_MINMAX, hook|lparam, 0, SW_RESTORE }, { WM_GETTEXT, sent|optional }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, { WM_GETMINMAXINFO, sent|defwinproc }, { WM_NCCALCSIZE, sent|wparam, TRUE }, { WM_NCPAINT, sent|optional }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED, 0, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOSIZE|SWP_NOMOVE }, { WM_MOVE, sent|defwinproc|optional }, { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, { WM_NCCALCSIZE, sent|wparam|optional, TRUE }, { WM_NCPAINT, sent|optional }, { WM_ERASEBKGND, sent|optional }, { WM_PAINT, sent|optional }, { WM_GETTITLEBARINFOEX, sent|optional }, { WM_NCPAINT, sent|beginpaint|optional }, { WM_ERASEBKGND, sent|beginpaint|optional }, { WM_SYNCPAINT, sent|optional }, { 0 }};/* ShowWindow(SW_RESTORE) for a not visible minimized overlapped window */static const struct message WmShowRestoreMinOverlappedSeq[] = { { HCBT_MINMAX, hook|lparam, 0, SW_RESTORE }, { WM_QUERYOPEN, sent|optional }, { WM_GETTEXT, sent|optional }, { WM_NCACTIVATE, sent|wparam|optional, 1 }, { WM_WINDOWPOSCHANGING, sent|optional }, /* SWP_NOSIZE|SWP_NOMOVE */ { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { WM_NCCALCSIZE, sent|wparam|optional, TRUE }, { WM_MOVE, sent|optional }, { WM_SIZE, sent|wparam|optional, SIZE_RESTORED }, { WM_GETTEXT, sent|optional }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_FRAMECHANGED|SWP_STATECHANGED|SWP_NOCOPYBITS }, { WM_GETMINMAXINFO, sent|defwinproc|optional }, { WM_NCCALCSIZE, sent|wparam|optional, TRUE }, { HCBT_ACTIVATE, hook|optional }, { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, { WM_ACTIVATEAPP, sent|wparam|optional, 1 }, { WM_NCACTIVATE, sent|wparam|optional, 1 }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ACTIVATE, sent|wparam|optional, 1 }, { HCBT_SETFOCUS, hook|optional }, { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { WM_SETFOCUS, sent|wparam|defwinproc|optional, 0 }, { WM_GETTEXT, sent|optional }, { WM_NCPAINT, sent|wparam|optional, 1 }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_STATECHANGED|SWP_FRAMECHANGED|SWP_NOCOPYBITS }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, { HCBT_SETFOCUS, hook|optional }, { WM_SETFOCUS, sent|wparam|optional, 0 }, { WM_NCCALCSIZE, sent|wparam|optional, TRUE }, { WM_NCPAINT, sent|wparam|optional, 1 }, { WM_ERASEBKGND, sent|optional }, { HCBT_SETFOCUS, hook|optional }, { WM_SETFOCUS, sent|wparam|optional, 0 }, { WM_ACTIVATE, sent|wparam, 1 }, { WM_GETTEXT, sent|optional }, { WM_PAINT, sent|optional }, { WM_GETTITLEBARINFOEX, sent|optional }, { WM_NCPAINT, sent|beginpaint|optional }, { WM_ERASEBKGND, sent|beginpaint|optional }, { 0 }};/* ShowWindow(SW_SHOWMINIMIZED) for a not visible overlapped window */static const struct message WmShowMinOverlappedSeq[] = { { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE }, { HCBT_SETFOCUS, hook|optional }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_KILLFOCUS, sent|optional }, { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, { WM_IME_NOTIFY, sent|wparam|optional|defwinproc, 1 }, { WM_GETTEXT, sent|optional }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOCOPYBITS|SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_STATECHANGED }, { WM_GETMINMAXINFO, sent|defwinproc }, { WM_NCCALCSIZE, sent|wparam, TRUE }, { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, { WM_NCPAINT, sent|optional }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_WINDOWPOSCHANGED, sent }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|defwinproc|wparam|lparam, SIZE_MINIMIZED, 0 }, { WM_NCCALCSIZE, sent|optional }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 }, { WM_NCACTIVATE, sent|wparam|optional, 0 }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ACTIVATE, sent|optional }, { WM_ACTIVATEAPP, sent|wparam|optional, 0 },
/* Vista sometimes restores the window right away... */ { WM_SYSCOMMAND, sent|optional|wparam, SC_RESTORE }, { HCBT_SYSCOMMAND, hook|optional|wparam, SC_RESTORE }, { HCBT_MINMAX, hook|optional|lparam, 0, SW_RESTORE }, { WM_QUERYOPEN, sent|optional }, { WM_WINDOWPOSCHANGING, sent|optional|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, { WM_GETMINMAXINFO, sent|optional|defwinproc }, { WM_NCCALCSIZE, sent|optional|wparam, TRUE }, { HCBT_ACTIVATE, hook|optional }, { WM_ACTIVATEAPP, sent|optional|wparam, 1 }, { WM_NCACTIVATE, sent|optional }, { WM_GETTEXT, sent|optional }, { WM_ACTIVATE, sent|optional|wparam, 1 }, { HCBT_SETFOCUS, hook|optional }, { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { WM_SETFOCUS, sent|optional }, { WM_NCPAINT, sent|optional }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent|optional }, { WM_WINDOWPOSCHANGED, sent|optional|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, { WM_MOVE, sent|defwinproc|optional }, { WM_SIZE, sent|defwinproc|optional|wparam, SIZE_RESTORED }, { WM_ACTIVATE, sent|optional|wparam, 1 }, { WM_SYSCOMMAND, sent|optional|wparam, SC_RESTORE }, { HCBT_SYSCOMMAND, hook|optional|wparam, SC_RESTORE },
{ WM_PAINT, sent|optional }, { WM_NCPAINT, sent|beginpaint|optional }, { WM_ERASEBKGND, sent|beginpaint|optional }, { 0 }};/* ShowWindow(SW_HIDE) for a visible overlapped window */static const struct message WmHideOverlappedSeq[] = { { WM_SHOWWINDOW, sent|wparam, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { WM_SIZE, sent|optional }, /* XP doesn't send it */ { WM_MOVE, sent|optional }, /* XP doesn't send it */ { WM_NCACTIVATE, sent|wparam|optional, 0 }, { WM_ACTIVATE, sent|wparam|optional, 0 }, { WM_ACTIVATEAPP, sent|wparam|optional, 0 }, { HCBT_SETFOCUS, hook|optional }, { WM_KILLFOCUS, sent|wparam|optional, 0 }, { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, { WM_IME_NOTIFY, sent|wparam|optional|defwinproc, 1 }, { 0 }};/* DestroyWindow for a visible overlapped window */static const struct message WmDestroyOverlappedSeq[] = { { HCBT_DESTROYWND, hook }, { 0x0090, sent|optional }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, { 0x0090, sent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { WM_NCACTIVATE, sent|optional|wparam, 0 }, { WM_ACTIVATE, sent|optional }, { WM_ACTIVATEAPP, sent|optional|wparam, 0 }, { WM_KILLFOCUS, sent|optional|wparam, 0 }, { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, { WM_IME_NOTIFY, sent|wparam|optional|defwinproc, 1 }, { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, { WM_DESTROY, sent }, { WM_NCDESTROY, sent }, { 0 }};/* CreateWindow(WS_MAXIMIZE|WS_VISIBLE) for popup window */static const struct message WmCreateMaxPopupSeq[] = { { HCBT_CREATEWND, hook }, { WM_NCCREATE, sent }, { WM_NCCALCSIZE, sent|wparam, 0 }, { WM_CREATE, sent }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SIZE, sent|wparam, SIZE_RESTORED }, { WM_MOVE, sent }, { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, { WM_GETMINMAXINFO, sent }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_STATECHANGED }, { WM_NCCALCSIZE, sent|wparam, TRUE }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOREDRAW|SWP_STATECHANGED }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SHOWWINDOW, sent|wparam, 1 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { HCBT_ACTIVATE, hook }, { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, { WM_NCPAINT, sent|wparam|optional, 1 }, { WM_ERASEBKGND, sent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOCLIENTMOVE|SWP_NOCLIENTSIZE|SWP_NOMOVE|SWP_NOSIZE }, { WM_ACTIVATEAPP, sent|wparam, 1 }, { WM_NCACTIVATE, sent }, { WM_ACTIVATE, sent|wparam, 1 }, { HCBT_SETFOCUS, hook }, { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, { WM_GETTEXT, sent|optional }, { WM_SYNCPAINT, sent|wparam|optional, 4 }, { WM_NCPAINT, sent|wparam|optional, 1 }, { WM_ERASEBKGND, sent|optional }, { WM_NCPAINT, sent|wparam|defwinproc|optional, 1 }, { WM_ERASEBKGND, sent|defwinproc|optional }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTMOVE|SWP_NOCLIENTSIZE|SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOSIZE }, { 0 }};/* CreateWindow(WS_MAXIMIZE) for popup window, not initially visible */static const struct message WmCreateInvisibleMaxPopupSeq[] = { { HCBT_CREATEWND, hook }, { WM_NCCREATE, sent }, { WM_NCCALCSIZE, sent|wparam, 0 }, { WM_CREATE, sent }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SIZE, sent|wparam, SIZE_RESTORED }, { WM_MOVE, sent }, { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, { WM_GETMINMAXINFO, sent }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_STATECHANGED }, { WM_NCCALCSIZE, sent|wparam, TRUE }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOREDRAW|SWP_STATECHANGED }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { 0 }};/* ShowWindow(SW_SHOWMAXIMIZED) for a resized not visible popup window */static const struct message WmShowMaxPopupResizedSeq[] = { { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, { WM_GETMINMAXINFO, sent }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED }, { WM_NCCALCSIZE, sent|wparam, TRUE }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { HCBT_ACTIVATE, hook }, { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, { WM_NCPAINT, sent|wparam|optional, 1 }, { WM_ERASEBKGND, sent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { WM_ACTIVATEAPP, sent|wparam, 1 }, { WM_NCACTIVATE, sent }, { WM_ACTIVATE, sent|wparam, 1 }, { HCBT_SETFOCUS, hook }, { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, { WM_GETTEXT, sent|optional }, { WM_NCPAINT, sent|wparam|optional, 1 }, { WM_ERASEBKGND, sent|optional }, { WM_WINDOWPOSCHANGED, sent }, /* WinNT4.0 sends WM_MOVE */ { WM_MOVE, sent|defwinproc|optional }, { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { 0 }};/* ShowWindow(SW_SHOWMAXIMIZED) for a not visible popup window */static const struct message WmShowMaxPopupSeq[] = { { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, { WM_GETMINMAXINFO, sent }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED }, { WM_NCCALCSIZE, sent|wparam, TRUE }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { HCBT_ACTIVATE, hook }, { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, { WM_NCPAINT, sent|wparam|optional, 1 }, { WM_ERASEBKGND, sent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOMOVE|SWP_NOSIZE }, { WM_ACTIVATEAPP, sent|wparam, 1 }, { WM_NCACTIVATE, sent }, { WM_ACTIVATE, sent|wparam, 1 }, { HCBT_SETFOCUS, hook }, { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, { WM_GETTEXT, sent|optional }, { WM_SYNCPAINT, sent|wparam|optional, 4 }, { WM_NCPAINT, sent|wparam|optional, 1 }, { WM_ERASEBKGND, sent|optional }, { WM_NCPAINT, sent|wparam|defwinproc|optional, 1 }, { WM_ERASEBKGND, sent|defwinproc|optional }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOSIZE }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SIZE, sent|defwinproc|optional }, { 0 }};/* CreateWindow(WS_VISIBLE) for popup window */static const struct message WmCreatePopupSeq[] = { { HCBT_CREATEWND, hook }, { WM_NCCREATE, sent }, { WM_NCCALCSIZE, sent|wparam, 0 }, { WM_CREATE, sent }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SIZE, sent|wparam, SIZE_RESTORED }, { WM_MOVE, sent }, { WM_SHOWWINDOW, sent|wparam, 1 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { HCBT_ACTIVATE, hook }, { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, { WM_NCPAINT, sent|wparam|optional, 1 }, { WM_ERASEBKGND, sent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { WM_ACTIVATEAPP, sent|wparam, 1 }, { WM_NCACTIVATE, sent }, { WM_ACTIVATE, sent|wparam, 1 }, { HCBT_SETFOCUS, hook }, { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, { WM_GETTEXT, sent|optional }, { WM_SYNCPAINT, sent|wparam|optional, 4 }, { WM_NCPAINT, sent|wparam|optional, 1 }, { WM_ERASEBKGND, sent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTMOVE|SWP_NOCLIENTSIZE|SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOSIZE }, { 0 }};/* ShowWindow(SW_SHOWMAXIMIZED) for a visible popup window */static const struct message WmShowVisMaxPopupSeq[] = { { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, { WM_GETMINMAXINFO, sent }, { WM_GETTEXT, sent|optional }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, { WM_GETTEXT, sent|optional }, { WM_NCCALCSIZE, sent|wparam, TRUE }, { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, { WM_NCPAINT, sent|wparam|optional, 1 }, { WM_ERASEBKGND, sent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { 0 }};/* CreateWindow (for a child popup window, not initially visible) */static const struct message WmCreateChildPopupSeq[] = { { HCBT_CREATEWND, hook }, { WM_NCCREATE, sent }, { WM_NCCALCSIZE, sent|wparam, 0 }, { WM_CREATE, sent }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SIZE, sent|wparam, SIZE_RESTORED }, { WM_MOVE, sent }, { 0 }};/* CreateWindow (for a popup window, not initially visible, * which sets WS_VISIBLE in WM_CREATE handler) */static const struct message WmCreateInvisiblePopupSeq[] = { { HCBT_CREATEWND, hook }, { WM_NCCREATE, sent }, { WM_NCCALCSIZE, sent|wparam, 0 }, { WM_CREATE, sent }, { WM_STYLECHANGING, sent }, { WM_STYLECHANGED, sent }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SIZE, sent|wparam, SIZE_RESTORED }, { WM_MOVE, sent }, { 0 }};/* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER) * for a popup window with WS_VISIBLE style set */static const struct message WmShowVisiblePopupSeq_2[] = { { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { 0 }};/* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE) * for a popup window with WS_VISIBLE style set */static const struct message WmShowVisiblePopupSeq_3[] = { { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, { HCBT_ACTIVATE, hook }, { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, { WM_NCACTIVATE, sent }, { WM_ACTIVATE, sent|wparam, 1 }, { HCBT_SETFOCUS, hook }, { WM_KILLFOCUS, sent|parent }, { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|defwinproc }, { WM_GETTEXT, sent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE, 0, SWP_SHOWWINDOW }, { 0 }};/* CreateWindow (for a popup window with WS_VISIBLE style set and extreme location) */static const struct message WmShowPopupExtremeLocationSeq[] = { { HCBT_CREATEWND, hook }, { WM_NCCREATE, sent }, { WM_NCCALCSIZE, sent|wparam, 0 }, { WM_CREATE, sent }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SIZE, sent|wparam, SIZE_RESTORED }, { WM_MOVE, sent }, { WM_SHOWWINDOW, sent|wparam, 1 }, { WM_WINDOWPOSCHANGING, sent }, { HCBT_ACTIVATE, hook }, { WM_WINDOWPOSCHANGING, sent|optional }, { WM_QUERYNEWPALETTE, sent|optional }, { WM_ACTIVATEAPP, sent }, { WM_NCACTIVATE, sent }, { WM_ACTIVATE, sent }, { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { HCBT_SETFOCUS, hook }, { WM_SETFOCUS, sent|defwinproc }, { WM_NCPAINT, sent|wparam, 1 }, { WM_ERASEBKGND, sent }, { WM_WINDOWPOSCHANGED, sent }, /* occasionally received on test machines */ { WM_NCPAINT, sent|optional }, { WM_ERASEBKGND, sent|optional }, { 0 }};/* CreateWindow (for a popup window with WS_VISIBLE style set) */static const struct message WmShowPopupFirstDrawSeq_1[] = { { HCBT_CREATEWND, hook }, { WM_NCCREATE, sent }, { WM_NCCALCSIZE, sent|wparam, 0 }, { WM_CREATE, sent }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SIZE, sent|wparam, SIZE_RESTORED }, { WM_MOVE, sent }, { WM_SHOWWINDOW, sent|wparam, 1 }, { WM_WINDOWPOSCHANGING, sent }, { HCBT_ACTIVATE, hook }, { WM_WINDOWPOSCHANGING, sent|optional }, { WM_QUERYNEWPALETTE, sent|optional }, { WM_ACTIVATEAPP, sent }, { WM_NCACTIVATE, sent }, { WM_ACTIVATE, sent }, { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { HCBT_SETFOCUS, hook }, { WM_SETFOCUS, sent|defwinproc }, { WM_NCPAINT, sent|wparam, 1 }, { WM_ERASEBKGND, sent }, { WM_WINDOWPOSCHANGED, sent }, { WM_PAINT, sent }, /* occasionally received on test machines */ { WM_NCPAINT, sent|beginpaint|optional }, { WM_ERASEBKGND, sent|beginpaint|optional }, { 0 }};/* CreateWindow (for a popup window that is shown with ShowWindow(SW_SHOWMAXIMIZED)) */static const struct message WmShowPopupFirstDrawSeq_2[] = { { HCBT_CREATEWND, hook }, { WM_NCCREATE, sent }, { WM_NCCALCSIZE, sent|wparam, 0 }, { WM_CREATE, sent }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SIZE, sent|wparam, SIZE_RESTORED }, { WM_MOVE, sent }, { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, { WM_GETMINMAXINFO, sent }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_STATECHANGED|SWP_SHOWWINDOW|SWP_FRAMECHANGED }, { WM_NCCALCSIZE, sent|wparam, TRUE }, { HCBT_ACTIVATE, hook }, { WM_WINDOWPOSCHANGING, sent|optional }, { WM_NCPAINT, sent|optional|wparam, 1 }, { WM_ERASEBKGND, sent|optional }, { WM_WINDOWPOSCHANGED, sent|optional }, { WM_QUERYNEWPALETTE, sent|optional }, { WM_ACTIVATEAPP, sent }, { WM_NCACTIVATE, sent }, { WM_ACTIVATE, sent }, { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { HCBT_SETFOCUS, hook }, { WM_SETFOCUS, sent|defwinproc }, { WM_NCPAINT, sent|wparam, 1 }, { WM_ERASEBKGND, sent }, { WM_WINDOWPOSCHANGED, sent|optional }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|defwinproc, 0 }, { WM_PAINT, sent}, /* occasionally received on test machines */ { WM_NCPAINT, sent|beginpaint|optional }, { WM_ERASEBKGND, sent|beginpaint|optional }, { 0 }};static const struct message WmFirstDrawSetWindowPosSeq1[] = { { HCBT_CREATEWND, hook }, { WM_NCCREATE, sent }, { WM_NCCALCSIZE, sent|wparam, 0 }, { WM_CREATE, sent }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SIZE, sent|wparam, SIZE_RESTORED }, { WM_MOVE, sent }, { WM_WINDOWPOSCHANGING, sent }, { HCBT_ACTIVATE, hook }, { WM_WINDOWPOSCHANGING, sent|optional }, { WM_QUERYNEWPALETTE, sent|optional }, { WM_ACTIVATEAPP, sent }, { WM_NCACTIVATE, sent }, { WM_ACTIVATE, sent }, { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { HCBT_SETFOCUS, hook }, { WM_SETFOCUS, sent|defwinproc }, { WM_NCPAINT, sent|wparam, 1 }, { WM_ERASEBKGND, sent }, { WM_WINDOWPOSCHANGED, sent }, { WM_MOVE, sent|defwinproc }, { 0 }};static const struct message WmFirstDrawSetWindowPosSeq2[] = { { HCBT_CREATEWND, hook }, { WM_NCCREATE, sent }, { WM_NCCALCSIZE, sent|wparam, 0 }, { WM_CREATE, sent }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SIZE, sent|wparam, SIZE_RESTORED }, { WM_MOVE, sent }, { WM_WINDOWPOSCHANGING, sent }, { HCBT_ACTIVATE, hook }, { WM_QUERYNEWPALETTE, sent|optional }, { WM_WINDOWPOSCHANGING, sent|optional }, { WM_ACTIVATEAPP, sent }, { WM_NCACTIVATE, sent }, { WM_ACTIVATE, sent }, { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { HCBT_SETFOCUS, hook }, { WM_SETFOCUS, sent|defwinproc }, { WM_WINDOWPOSCHANGED, sent }, { WM_MOVE, sent|defwinproc }, { 0 }};static const struct message WmFirstDrawSetWindowPosSeq3[] = { { HCBT_CREATEWND, hook }, { WM_NCCREATE, sent }, { WM_NCCALCSIZE, sent|wparam, 0 }, { WM_CREATE, sent }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SIZE, sent|wparam, SIZE_RESTORED }, { WM_MOVE, sent }, { HCBT_ACTIVATE, hook|optional }, /* Probably shouldn't happen, but not part of this test */ { WM_QUERYNEWPALETTE, sent|optional }, { WM_ACTIVATEAPP, sent|optional }, { WM_NCACTIVATE, sent|optional }, { WM_ACTIVATE, sent|optional }, { HCBT_SETFOCUS, hook|optional }, { WM_SETFOCUS, sent|defwinproc|optional }, { 0 }};static const struct message WmFirstDrawSetWindowPosSeq4[] = { { HCBT_CREATEWND, hook }, { WM_NCCREATE, sent }, { WM_NCCALCSIZE, sent|wparam, 0 }, { WM_CREATE, sent }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SIZE, sent|wparam, SIZE_RESTORED }, { WM_MOVE, sent }, { WM_WINDOWPOSCHANGING, sent }, { HCBT_ACTIVATE, hook }, { WM_WINDOWPOSCHANGING, sent|optional }, { WM_QUERYNEWPALETTE, sent|optional }, { WM_ACTIVATEAPP, sent }, { WM_NCACTIVATE, sent }, { WM_ACTIVATE, sent }, { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { HCBT_SETFOCUS, hook }, { WM_SETFOCUS, sent|defwinproc }, { WM_NCPAINT, sent|wparam, 1 }, { WM_ERASEBKGND, sent }, { WM_WINDOWPOSCHANGED, sent }, { 0 }};static const struct message WmFirstDrawSetWindowPosSeq5[] = { { HCBT_CREATEWND, hook }, { WM_NCCREATE, sent }, { WM_NCCALCSIZE, sent|wparam, 0 }, { WM_CREATE, sent }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SIZE, sent|wparam, SIZE_RESTORED }, { WM_MOVE, sent }, { WM_WINDOWPOSCHANGING, sent }, { HCBT_ACTIVATE, hook }, { WM_WINDOWPOSCHANGING, sent|optional }, { WM_QUERYNEWPALETTE, sent|optional }, { WM_ACTIVATEAPP, sent }, { WM_NCACTIVATE, sent }, { WM_ACTIVATE, sent }, { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { HCBT_SETFOCUS, hook }, { WM_SETFOCUS, sent|defwinproc }, { WM_WINDOWPOSCHANGED, sent }, { 0 }};static const struct message WmFirstDrawChildSeq1[] = { { 0 }};static const struct message WmFirstDrawChildSeq2[] = { { WM_NCPAINT, sent|wparam, 1 }, { WM_ERASEBKGND, sent }, /* occasionally received on test machines */ { WM_NCPAINT, sent|optional }, { WM_ERASEBKGND, sent|optional }, { 0 }};/* CreateWindow (for child window, not initially visible) */static const struct message WmCreateChildSeq[] = { { HCBT_CREATEWND, hook }, { WM_NCCREATE, sent }, /* child is inserted into parent's child list after WM_NCCREATE returns */ { WM_NCCALCSIZE, sent|wparam, 0 }, { WM_CREATE, sent }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SIZE, sent|wparam, SIZE_RESTORED }, { WM_MOVE, sent }, { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE }, { 0 }};/* CreateWindow (for maximized child window, not initially visible) */static const struct message WmCreateMaximizedChildSeq[] = { { HCBT_CREATEWND, hook }, { WM_NCCREATE, sent }, { WM_NCCALCSIZE, sent|wparam, 0 }, { WM_CREATE, sent }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SIZE, sent|wparam, SIZE_RESTORED }, { WM_MOVE, sent }, { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, { WM_GETMINMAXINFO, sent }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_STATECHANGED }, { WM_NCCALCSIZE, sent|wparam, 1 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE }, { 0 }};/* CreateWindow (for a child window, initially visible) */static const struct message WmCreateVisibleChildSeq[] = { { HCBT_CREATEWND, hook }, { WM_NCCREATE, sent }, /* child is inserted into parent's child list after WM_NCCREATE returns */ { WM_NCCALCSIZE, sent|wparam, 0 }, { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, { WM_CREATE, sent }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SIZE, sent|wparam, SIZE_RESTORED }, { WM_MOVE, sent }, { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE }, { WM_SHOWWINDOW, sent|wparam, 1 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { WM_ERASEBKGND, sent|parent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* WinXP */ { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { 0 }};/* ShowWindow(SW_SHOW) for a not visible child window */static const struct message WmShowChildSeq[] = { { WM_SHOWWINDOW, sent|wparam, 1 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { WM_ERASEBKGND, sent|parent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { 0 }};/* ShowWindow(SW_HIDE) for a visible child window */static const struct message WmHideChildSeq[] = { { WM_SHOWWINDOW, sent|wparam, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, { WM_ERASEBKGND, sent|parent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { 0 }};/* ShowWindow(SW_HIDE) for a visible child window checking all parent events*/static const struct message WmHideChildSeq2[] = { { WM_SHOWWINDOW, sent|wparam, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, { WM_ERASEBKGND, sent|parent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { 0 }};/* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE) * for a not visible child window */static const struct message WmShowChildSeq_2[] = { { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { WM_CHILDACTIVATE, sent }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { 0 }};/* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE) * for a not visible child window */static const struct message WmShowChildSeq_3[] = { { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { 0 }};/* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE) * for a visible child window with a caption */static const struct message WmShowChildSeq_4[] = { { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, { WM_CHILDACTIVATE, sent }, { 0 }};/* ShowWindow(SW_MINIMIZE) for child with invisible parent */static const struct message WmShowChildInvisibleParentSeq_1[] = { { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED, 0, SWP_NOACTIVATE }, { WM_NCCALCSIZE, sent|wparam, 1 }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { WM_CHILDACTIVATE, sent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOREDRAW|SWP_NOCOPYBITS|SWP_STATECHANGED, 0, SWP_NOACTIVATE }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|defwinproc|wparam|lparam, SIZE_MINIMIZED, 0 }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 }, /* FIXME: Wine creates an icon/title window while Windows doesn't */ { WM_PARENTNOTIFY, sent|parent|wparam|optional, WM_CREATE }, { WM_GETTEXT, sent|optional }, { 0 }};/* repeated ShowWindow(SW_MINIMIZE) for child with invisible parent */static const struct message WmShowChildInvisibleParentSeq_1r[] = { { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE }, { 0 }};/* ShowWindow(SW_MAXIMIZE) for child with invisible parent */static const struct message WmShowChildInvisibleParentSeq_2[] = { { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, { WM_GETMINMAXINFO, sent }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_STATECHANGED }, { WM_NCCALCSIZE, sent|wparam, 1 }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { WM_CHILDACTIVATE, sent }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { 0 }};/* repeated ShowWindow(SW_MAXIMIZE) for child with invisible parent */static const struct message WmShowChildInvisibleParentSeq_2r[] = { { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, { 0 }};/* ShowWindow(SW_SHOWMINIMIZED) for child with invisible parent */static const struct message WmShowChildInvisibleParentSeq_3[] = { { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINIMIZED }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, { WM_NCCALCSIZE, sent|wparam, 1 }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { WM_CHILDACTIVATE, sent }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOREDRAW|SWP_NOCOPYBITS|SWP_STATECHANGED }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|defwinproc|wparam|lparam, SIZE_MINIMIZED, 0 }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 }, /* FIXME: Wine creates an icon/title window while Windows doesn't */ { WM_PARENTNOTIFY, sent|parent|wparam|optional, WM_CREATE }, { WM_GETTEXT, sent|optional }, { 0 }};/* repeated ShowWindow(SW_SHOWMINIMIZED) for child with invisible parent */static const struct message WmShowChildInvisibleParentSeq_3r[] = { { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINIMIZED }, { 0 }};/* ShowWindow(SW_SHOWMINNOACTIVE) for child with invisible parent */static const struct message WmShowChildInvisibleParentSeq_4[] = { { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINNOACTIVE }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_STATECHANGED }, { WM_NCCALCSIZE, sent|wparam, 1 }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOREDRAW|SWP_NOCOPYBITS|SWP_STATECHANGED }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|defwinproc|wparam|lparam, SIZE_MINIMIZED, 0 }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 }, /* FIXME: Wine creates an icon/title window while Windows doesn't */ { WM_PARENTNOTIFY, sent|parent|wparam|optional, WM_CREATE }, { WM_GETTEXT, sent|optional }, { 0 }};/* repeated ShowWindow(SW_SHOWMINNOACTIVE) for child with invisible parent */static const struct message WmShowChildInvisibleParentSeq_4r[] = { { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINNOACTIVE }, { 0 }};/* ShowWindow(SW_SHOW) for child with invisible parent */static const struct message WmShowChildInvisibleParentSeq_5[] = { { WM_SHOWWINDOW, sent|wparam, 1 }, { 0 }};/* ShowWindow(SW_HIDE) for child with invisible parent */static const struct message WmHideChildInvisibleParentSeq[] = { { WM_SHOWWINDOW, sent|wparam, 0 }, { 0 }};/* SetWindowPos(SWP_SHOWWINDOW) for child with invisible parent */static const struct message WmShowChildInvisibleParentSeq_6[] = { { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { 0 }};/* SetWindowPos(SWP_HIDEWINDOW) for child with invisible parent */static const struct message WmHideChildInvisibleParentSeq_2[] = { { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { 0 }};/* DestroyWindow for a visible child window */static const struct message WmDestroyChildSeq[] = { { HCBT_DESTROYWND, hook }, { 0x0090, sent|optional }, { WM_PARENTNOTIFY, sent|parent|wparam, WM_DESTROY }, { WM_SHOWWINDOW, sent|wparam, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, { WM_ERASEBKGND, sent|parent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { HCBT_SETFOCUS, hook }, /* set focus to a parent */ { WM_KILLFOCUS, sent }, { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, { WM_IME_SETCONTEXT, sent|wparam|parent|optional, 1 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|parent }, { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, { WM_DESTROY, sent }, { WM_DESTROY, sent|optional }, /* some other (IME?) window */ { WM_NCDESTROY, sent|optional }, /* some other (IME?) window */ { WM_NCDESTROY, sent }, { 0 }};/* visible child window destroyed by thread exit */static const struct message WmExitThreadSeq[] = { { WM_NCDESTROY, sent }, /* actually in grandchild */ { WM_PAINT, sent|parent }, { WM_ERASEBKGND, sent|parent|beginpaint }, { 0 }};/* DestroyWindow for a visible child window with invisible parent */static const struct message WmDestroyInvisibleChildSeq[] = { { HCBT_DESTROYWND, hook }, { 0x0090, sent|optional }, { WM_PARENTNOTIFY, sent|parent|wparam, WM_DESTROY }, { WM_SHOWWINDOW, sent|wparam, 0 }, { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, { WM_DESTROY, sent }, { WM_NCDESTROY, sent }, { 0 }};/* Resizing child window with MoveWindow (32) */static const struct message WmResizingChildWithMoveWindowSeq[] = { { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE }, { WM_NCCALCSIZE, sent|wparam, 1 }, { WM_ERASEBKGND, sent|parent|optional }, { WM_ERASEBKGND, sent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { 0 }};/* Creation of a custom dialog (32) */static const struct message WmCreateCustomDialogSeq[] = { { HCBT_CREATEWND, hook }, { WM_GETMINMAXINFO, sent }, { WM_NCCREATE, sent }, { WM_NCCALCSIZE, sent|wparam, 0 }, { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, { WM_CREATE, sent }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, { WM_NOTIFYFORMAT, sent|optional }, { WM_QUERYUISTATE, sent|optional }, { WM_WINDOWPOSCHANGING, sent|optional }, { WM_GETMINMAXINFO, sent|optional }, { WM_NCCALCSIZE, sent|optional }, { WM_WINDOWPOSCHANGED, sent|optional }, { WM_SHOWWINDOW, sent|wparam, 1 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { HCBT_ACTIVATE, hook }, { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
{ WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
{ WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE },
{ WM_NCACTIVATE, sent }, { WM_GETTEXT, sent|optional|defwinproc }, { WM_GETTEXT, sent|optional|defwinproc }, { WM_GETTEXT, sent|optional|defwinproc }, { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 }, { WM_ACTIVATE, sent|wparam, 1 }, { WM_GETTEXT, sent|optional }, { WM_KILLFOCUS, sent|parent }, { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent }, { WM_GETDLGCODE, sent|defwinproc|wparam, 0 }, { WM_NCPAINT, sent|wparam, 1 }, { WM_GETTEXT, sent|optional|defwinproc }, { WM_GETTEXT, sent|optional|defwinproc }, { WM_ERASEBKGND, sent }, { WM_CTLCOLORDLG, sent|optional|defwinproc }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { WM_GETTEXT, sent|optional }, { WM_GETTEXT, sent|optional }, { WM_NCCALCSIZE, sent|optional }, { WM_NCPAINT, sent|optional }, { WM_GETTEXT, sent|optional|defwinproc }, { WM_GETTEXT, sent|optional|defwinproc }, { WM_ERASEBKGND, sent|optional }, { WM_CTLCOLORDLG, sent|optional|defwinproc }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SIZE, sent|wparam, SIZE_RESTORED }, { WM_MOVE, sent }, { 0 }};/* Calling EndDialog for a custom dialog (32) */static const struct message WmEndCustomDialogSeq[] = { { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { WM_GETTEXT, sent|optional }, { HCBT_ACTIVATE, hook }, { WM_NCACTIVATE, sent|wparam, 0 }, { WM_GETTEXT, sent|optional|defwinproc }, { WM_GETTEXT, sent|optional|defwinproc }, { WM_ACTIVATE, sent|wparam, 0 }, { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOACTIVATE|SWP_NOREDRAW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { WM_GETTEXT, sent|optional|defwinproc }, { WM_GETTEXT, sent|optional|defwinproc }, { HCBT_SETFOCUS, hook }, { WM_KILLFOCUS, sent }, { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, { WM_IME_SETCONTEXT, sent|parent|wparam|defwinproc|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|optional, 1 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|parent|defwinproc }, { 0 }};/* ShowWindow(SW_SHOW) for a custom dialog (initially invisible) */static const struct message WmShowCustomDialogSeq[] = { { WM_SHOWWINDOW, sent|wparam, 1 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { HCBT_ACTIVATE, hook }, { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
{ WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
{ WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, { WM_ACTIVATEAPP, sent|wparam|optional, 1 }, { WM_NCACTIVATE, sent }, { WM_ACTIVATE, sent|wparam, 1 }, { WM_GETTEXT, sent|optional },
{ WM_KILLFOCUS, sent|parent }, { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent }, { WM_GETDLGCODE, sent|defwinproc|wparam, 0 }, { WM_NCPAINT, sent|wparam, 1 }, { WM_ERASEBKGND, sent }, { WM_CTLCOLORDLG, sent|defwinproc }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { 0 }};/* Creation and destruction of a modal dialog (32) */static const struct message WmModalDialogSeq[] = { { WM_CANCELMODE, sent|parent }, { HCBT_SETFOCUS, hook }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_KILLFOCUS, sent|parent }, { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 }, { WM_ENABLE, sent|parent|wparam, 0 }, { HCBT_CREATEWND, hook }, { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SETFONT, sent }, { WM_INITDIALOG, sent }, { WM_CHANGEUISTATE, sent|optional }, { WM_UPDATEUISTATE, sent|optional }, { WM_SHOWWINDOW, sent }, { HCBT_ACTIVATE, hook }, { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE }, { WM_NCACTIVATE, sent }, { WM_GETTEXT, sent|optional }, { WM_ACTIVATE, sent|wparam, 1 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { WM_NCPAINT, sent|optional }, { WM_GETTEXT, sent|optional }, { WM_ERASEBKGND, sent|optional }, { WM_CTLCOLORDLG, sent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { WM_GETTEXT, sent|optional }, { WM_NCCALCSIZE, sent|optional }, { WM_NCPAINT, sent|optional }, { WM_GETTEXT, sent|optional }, { WM_ERASEBKGND, sent|optional }, { WM_CTLCOLORDLG, sent|optional }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { WM_PAINT, sent|optional }, { WM_CTLCOLORBTN, sent|optional }, { WM_GETTITLEBARINFOEX, sent|optional }, { WM_ENTERIDLE, sent|parent|optional }, { WM_ENTERIDLE, sent|parent|optional }, { WM_ENTERIDLE, sent|parent|optional }, { WM_ENTERIDLE, sent|parent|optional }, { WM_ENTERIDLE, sent|parent|optional }, { WM_ENTERIDLE, sent|parent|optional }, { WM_ENTERIDLE, sent|parent|optional }, { WM_ENTERIDLE, sent|parent|optional }, { WM_ENTERIDLE, sent|parent|optional }, { WM_ENTERIDLE, sent|parent|optional }, { WM_ENTERIDLE, sent|parent|optional }, { WM_ENTERIDLE, sent|parent|optional }, { WM_ENTERIDLE, sent|parent|optional }, { WM_ENTERIDLE, sent|parent|optional }, { WM_ENTERIDLE, sent|parent|optional }, { WM_ENTERIDLE, sent|parent|optional }, { WM_ENTERIDLE, sent|parent|optional }, { WM_ENTERIDLE, sent|parent|optional }, { WM_ENTERIDLE, sent|parent|optional }, { WM_ENTERIDLE, sent|parent|optional }, { WM_TIMER, sent }, { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 }, { WM_ENABLE, sent|parent|wparam, 1 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { WM_GETTEXT, sent|optional }, { HCBT_ACTIVATE, hook }, { WM_NCACTIVATE, sent|wparam, 0 }, { WM_GETTEXT, sent|optional }, { WM_ACTIVATE, sent|wparam, 0 }, { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGING, sent|optional }, { WM_WINDOWPOSCHANGED, sent|optional }, { HCBT_SETFOCUS, hook }, { WM_IME_SETCONTEXT, sent|parent|wparam|defwinproc|optional, 1 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|parent|defwinproc }, { EVENT_SYSTEM_DIALOGEND, winevent_hook|wparam|lparam, 0, 0 }, { HCBT_DESTROYWND, hook }, { 0x0090, sent|optional }, { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, { WM_DESTROY, sent }, { WM_NCDESTROY, sent }, { 0 }};static const struct message WmModalDialogSeq_2[] = { { WM_CANCELMODE, sent }, { HCBT_SETFOCUS, hook }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_KILLFOCUS, sent }, { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 }, { WM_ENABLE, sent|wparam, 0 }, { HCBT_CREATEWND, hook }, { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SETFONT, sent }, { WM_INITDIALOG, sent }, { WM_CHANGEUISTATE, sent|optional }, { WM_UPDATEUISTATE, sent|optional }, { WM_ENABLE, sent|wparam, 1 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, { WM_CHANGEUISTATE, sent|optional }, { WM_UPDATEUISTATE, sent|optional }, { HCBT_DESTROYWND, hook }, { 0x0090, sent|optional }, { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, { WM_DESTROY, sent }, { WM_NCDESTROY, sent }, { 0 }};/* SetMenu for NonVisible windows with size change*/static const struct message WmSetMenuNonVisibleSizeChangeSeq[] = { { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCCALCSIZE, sent|wparam, 1 }, { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, { WM_NCCALCSIZE,sent|wparam|optional, 1 }, /* XP */ { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP sends a duplicate */ { WM_GETTEXT, sent|optional }, { WM_NCCALCSIZE, sent|wparam|optional, 1 }, { 0 }};/* SetMenu for NonVisible windows with no size change */static const struct message WmSetMenuNonVisibleNoSizeChangeSeq[] = { { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCCALCSIZE, sent|wparam, 1 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { 0 }};/* SetMenu for Visible windows with size change */static const struct message WmSetMenuVisibleSizeChangeSeq[] = { { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCCALCSIZE, sent|wparam, 1 }, { 0x0093, sent|defwinproc|optional }, { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, { WM_NCPAINT, sent|optional }, /* wparam != 1 */ { 0x0093, sent|defwinproc|optional }, { 0x0093, sent|defwinproc|optional }, { 0x0091, sent|defwinproc|optional }, { 0x0092, sent|defwinproc|optional }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent|optional }, { WM_ACTIVATE, sent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, { 0x0093, sent|optional }, { WM_NCCALCSIZE, sent|wparam|optional, 1 }, { 0x0093, sent|defwinproc|optional }, { WM_NCPAINT, sent|optional }, /* wparam != 1 */ { 0x0093, sent|defwinproc|optional }, { 0x0093, sent|defwinproc|optional }, { 0x0091, sent|defwinproc|optional }, { 0x0092, sent|defwinproc|optional }, { WM_ERASEBKGND, sent|optional }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP sends a duplicate */ { 0 }};/* SetMenu for Visible windows with no size change */static const struct message WmSetMenuVisibleNoSizeChangeSeq[] = { { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCCALCSIZE, sent|wparam, 1 }, { WM_NCPAINT, sent|optional }, /* wparam != 1 */ { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent|optional }, { WM_ACTIVATE, sent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { 0 }};/* DrawMenuBar for a visible window */static const struct message WmDrawMenuBarSeq[] ={ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCCALCSIZE, sent|wparam, 1 }, { 0x0093, sent|defwinproc|optional }, { WM_NCPAINT, sent|optional }, /* wparam != 1 */ { 0x0093, sent|defwinproc|optional }, { 0x0093, sent|defwinproc|optional }, { 0x0091, sent|defwinproc|optional }, { 0x0092, sent|defwinproc|optional }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { 0x0093, sent|optional }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { 0 }};
static const struct message WmSetRedrawFalseSeq[] ={ { WM_SETREDRAW, sent|wparam, 0 }, { 0 }};
static const struct message WmSetRedrawTrueSeq[] ={ { WM_SETREDRAW, sent|wparam, 1 }, { 0 }};
static const struct message WmEnableWindowSeq_1[] ={ { WM_CANCELMODE, sent|wparam|lparam, 0, 0 }, { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 }, { HCBT_SETFOCUS, hook|optional }, { WM_KILLFOCUS, sent|optional }, { WM_ENABLE, sent|wparam|lparam, FALSE, 0 }, { 0 }};
static const struct message WmEnableWindowSeq_2[] ={ { WM_CANCELMODE, sent|wparam|lparam, 0, 0 }, { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 }, { 0 }};
static const struct message WmEnableWindowSeq_3[] ={ { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 }, { WM_ENABLE, sent|wparam|lparam, TRUE, 0 }, { 0 }};
static const struct message WmEnableWindowSeq_4[] ={ { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 }, { 0 }};
static const struct message WmGetScrollRangeSeq[] ={ { SBM_GETRANGE, sent }, { 0 }};static const struct message WmGetScrollInfoSeq[] ={ { SBM_GETSCROLLINFO, sent }, { 0 }};static const struct message WmSetScrollRangeSeq[] ={ /* MSDN claims that Windows sends SBM_SETRANGE message, but win2k SP4 sends SBM_SETSCROLLINFO. */ { SBM_SETSCROLLINFO, sent }, { 0 }};/* SetScrollRange for a window without a non-client area */static const struct message WmSetScrollRangeHSeq_empty[] ={ { EVENT_OBJECT_VALUECHANGE, winevent_hook|wparam|lparam, OBJID_HSCROLL, 0 }, { 0 }};static const struct message WmSetScrollRangeVSeq_empty[] ={ { EVENT_OBJECT_VALUECHANGE, winevent_hook|wparam|lparam, OBJID_VSCROLL, 0 }, { 0 }};static const struct message WmSetScrollRangeHVSeq[] ={ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE }, { WM_NCCALCSIZE, sent|wparam, 1 }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { EVENT_OBJECT_VALUECHANGE, winevent_hook|lparam|optional, 0/*OBJID_HSCROLL or OBJID_VSCROLL*/, 0 }, { 0 }};/* SetScrollRange for a window with a non-client area */static const struct message WmSetScrollRangeHV_NC_Seq[] ={ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE }, { WM_NCCALCSIZE, sent|wparam, 1 }, { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, { WM_NCPAINT, sent|optional }, { WM_STYLECHANGING, sent|defwinproc|optional }, { WM_STYLECHANGED, sent|defwinproc|optional }, { WM_STYLECHANGING, sent|defwinproc|optional }, { WM_STYLECHANGED, sent|defwinproc|optional }, { WM_STYLECHANGING, sent|defwinproc|optional }, { WM_STYLECHANGED, sent|defwinproc|optional }, { WM_STYLECHANGING, sent|defwinproc|optional }, { WM_STYLECHANGED, sent|defwinproc|optional }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent|optional }, { WM_CTLCOLORDLG, sent|defwinproc|optional }, /* sent to a parent of the dialog */ { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOCLIENTMOVE, 0, SWP_NOCLIENTSIZE }, { WM_SIZE, sent|defwinproc|optional }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { EVENT_OBJECT_VALUECHANGE, winevent_hook|lparam|optional, 0/*OBJID_HSCROLL or OBJID_VSCROLL*/, 0 }, { WM_GETTEXT, sent|optional }, { WM_GETTEXT, sent|optional }, { WM_GETTEXT, sent|optional }, { WM_GETTEXT, sent|optional }, { 0 }};/* test if we receive the right sequence of messages *//* after calling ShowWindow( SW_SHOWNA) */static const struct message WmSHOWNAChildInvisParInvis[] = { { WM_SHOWWINDOW, sent|wparam, 1 }, { 0 }};static const struct message WmSHOWNAChildVisParInvis[] = { { WM_SHOWWINDOW, sent|wparam, 1 }, { 0 }};static const struct message WmSHOWNAChildVisParVis[] = { { WM_SHOWWINDOW, sent|wparam, 1 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, { 0 }};static const struct message WmSHOWNAChildInvisParVis[] = { { WM_SHOWWINDOW, sent|wparam, 1 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { WM_ERASEBKGND, sent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOACTIVATE|SWP_NOCLIENTMOVE }, { 0 }};static const struct message WmSHOWNATopVisible[] = { { WM_SHOWWINDOW, sent|wparam, 1 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, { WM_NCPAINT, sent|wparam|optional, 1 }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent|optional }, { WM_WINDOWPOSCHANGED, sent|optional }, { 0 }};static const struct message WmSHOWNATopInvisible[] = { { WM_NOTIFYFORMAT, sent|optional }, { WM_QUERYUISTATE, sent|optional }, { WM_WINDOWPOSCHANGING, sent|optional }, { WM_GETMINMAXINFO, sent|optional }, { WM_NCCALCSIZE, sent|optional }, { WM_WINDOWPOSCHANGED, sent|optional }, { WM_SHOWWINDOW, sent|wparam, 1 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { WM_NCPAINT, sent|wparam|optional, 1 }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { WM_NCCALCSIZE, sent|wparam|optional, 1 }, { WM_NCPAINT, sent|wparam|optional, 1 }, { WM_ERASEBKGND, sent|optional }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SIZE, sent|wparam, SIZE_RESTORED }, { WM_MOVE, sent }, { 0 }};
static const struct message WmTrackPopupMenu[] = { { HCBT_CREATEWND, hook }, { WM_ENTERMENULOOP, sent|wparam|lparam, TRUE, 0 }, { WM_INITMENU, sent|lparam, 0, 0 }, { WM_INITMENUPOPUP, sent|lparam, 0, 0 }, { 0x0093, sent|optional }, { 0x0094, sent|optional }, { 0x0094, sent|optional }, { WM_ENTERIDLE, sent|wparam, 2 }, { WM_CAPTURECHANGED, sent }, { HCBT_DESTROYWND, hook }, { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, { WM_MENUSELECT, sent|wparam|lparam, 0xffff0000, 0 }, { WM_EXITMENULOOP, sent|wparam|lparam, 1, 0 }, { 0 }};
static const struct message WmTrackPopupMenuEsc[] = { { 0 }};
static const struct message WmTrackPopupMenuCapture[] = { { HCBT_CREATEWND, hook }, { WM_ENTERMENULOOP, sent|wparam|lparam, TRUE, 0 }, { WM_CAPTURECHANGED, sent }, { WM_INITMENU, sent|lparam, 0, 0 }, { WM_INITMENUPOPUP, sent|lparam, 0, 0 }, { 0x0093, sent|optional }, { 0x0094, sent|optional }, { 0x0094, sent|optional }, { WM_ENTERIDLE, sent|wparam, 2 }, { WM_CAPTURECHANGED, sent }, { HCBT_DESTROYWND, hook }, { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, { WM_MENUSELECT, sent|wparam|lparam, 0xffff0000, 0 }, { WM_EXITMENULOOP, sent|wparam|lparam, 1, 0 }, { 0 }};
static const struct message WmTrackPopupMenuEmpty[] = { { HCBT_CREATEWND, hook }, { WM_ENTERMENULOOP, sent|wparam|lparam, TRUE, 0 }, { WM_INITMENU, sent|lparam, 0, 0 }, { WM_INITMENUPOPUP, sent|lparam, 0, 0 }, { 0x0093, sent|optional }, { 0x0094, sent|optional }, { 0x0094, sent|optional }, { WM_CAPTURECHANGED, sent }, { WM_EXITMENULOOP, sent|wparam|lparam, 1, 0 }, { HCBT_DESTROYWND, hook }, { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, { 0 }};
static const struct message WmTrackPopupMenuAbort[] = { { HCBT_CREATEWND, hook }, { WM_ENTERMENULOOP, sent|wparam|lparam, TRUE, 0 }, { WM_INITMENU, sent|lparam, 0, 0 }, { WM_INITMENUPOPUP, sent|lparam, 0, 0 }, { 0x0093, sent|optional }, { 0x0094, sent|optional }, { 0x0094, sent|optional }, { WM_CAPTURECHANGED, sent }, { HCBT_DESTROYWND, hook }, { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, { WM_MENUSELECT, sent|wparam|lparam, 0xffff0000, 0 }, { WM_EXITMENULOOP, sent|wparam|lparam, 1, 0 }, { 0 }};
static BOOL after_end_dialog, test_def_id, paint_loop_done;static int sequence_cnt, sequence_size;static struct recvd_message* sequence;static int log_all_parent_messages;static CRITICAL_SECTION sequence_cs;
/* user32 functions */static HWND (WINAPI *pGetAncestor)(HWND,UINT);static BOOL (WINAPI *pGetMenuInfo)(HMENU,LPCMENUINFO);static void (WINAPI *pNotifyWinEvent)(DWORD, HWND, LONG, LONG);static BOOL (WINAPI *pSetMenuInfo)(HMENU,LPCMENUINFO);static HWINEVENTHOOK (WINAPI *pSetWinEventHook)(DWORD, DWORD, HMODULE, WINEVENTPROC, DWORD, DWORD, DWORD);static BOOL (WINAPI *pTrackMouseEvent)(TRACKMOUSEEVENT*);static BOOL (WINAPI *pUnhookWinEvent)(HWINEVENTHOOK);static BOOL (WINAPI *pGetMonitorInfoA)(HMONITOR,LPMONITORINFO);static HMONITOR (WINAPI *pMonitorFromPoint)(POINT,DWORD);static BOOL (WINAPI *pUpdateLayeredWindow)(HWND,HDC,POINT*,SIZE*,HDC,POINT*,COLORREF,BLENDFUNCTION*,DWORD);static UINT_PTR (WINAPI *pSetSystemTimer)(HWND, UINT_PTR, UINT, TIMERPROC);static UINT_PTR (WINAPI *pKillSystemTimer)(HWND, UINT_PTR);static UINT_PTR (WINAPI *pSetCoalescableTimer)(HWND, UINT_PTR, UINT, TIMERPROC, ULONG);/* kernel32 functions */static BOOL (WINAPI *pGetCPInfoExA)(UINT, DWORD, LPCPINFOEXA);
static void init_procs(void){ HMODULE user32 = GetModuleHandleA("user32.dll"); HMODULE kernel32 = GetModuleHandleA("kernel32.dll");
#define GET_PROC(dll, func) \ p ## func = (void*)GetProcAddress(dll, #func); \ if(!p ## func) { \ trace("GetProcAddress(%s) failed\n", #func); \ }
GET_PROC(user32, GetAncestor) GET_PROC(user32, GetMenuInfo) GET_PROC(user32, NotifyWinEvent) GET_PROC(user32, SetMenuInfo) GET_PROC(user32, SetWinEventHook) GET_PROC(user32, TrackMouseEvent) GET_PROC(user32, UnhookWinEvent) GET_PROC(user32, GetMonitorInfoA) GET_PROC(user32, MonitorFromPoint) GET_PROC(user32, UpdateLayeredWindow) GET_PROC(user32, SetSystemTimer) GET_PROC(user32, KillSystemTimer) GET_PROC(user32, SetCoalescableTimer)
GET_PROC(kernel32, GetCPInfoExA)
#undef GET_PROC}
static const char *get_winpos_flags(UINT flags){ static char buffer[300];
buffer[0] = 0;#define DUMP(flag) do { if (flags & flag) { strcat( buffer, "|" #flag ); flags &= ~flag; } } while(0) DUMP( SWP_SHOWWINDOW ); DUMP( SWP_HIDEWINDOW ); DUMP( SWP_NOACTIVATE ); DUMP( SWP_FRAMECHANGED ); DUMP( SWP_NOCOPYBITS ); DUMP( SWP_NOOWNERZORDER ); DUMP( SWP_NOSENDCHANGING ); DUMP( SWP_DEFERERASE ); DUMP( SWP_ASYNCWINDOWPOS ); DUMP( SWP_NOZORDER ); DUMP( SWP_NOREDRAW ); DUMP( SWP_NOSIZE ); DUMP( SWP_NOMOVE ); DUMP( SWP_NOCLIENTSIZE ); DUMP( SWP_NOCLIENTMOVE ); if (flags) sprintf(buffer + strlen(buffer),"|0x%04x", flags); return buffer + 1;#undef DUMP}
static BOOL ignore_message( UINT message ){ /* these are always ignored */ return (message >= 0xc000 || message == WM_GETICON || message == WM_GETOBJECT || message == WM_TIMECHANGE || message == WM_DISPLAYCHANGE || message == WM_DEVICECHANGE || message == WM_DWMNCRENDERINGCHANGED);}
static unsigned hash_Ly_W(const WCHAR *str){ unsigned hash = 0;
for (; *str; str++) hash = hash * 1664525u + (unsigned char)(*str) + 1013904223u;
return hash;}
static unsigned hash_Ly(const char *str){ unsigned hash = 0;
for (; *str; str++) hash = hash * 1664525u + (unsigned char)(*str) + 1013904223u;
return hash;}
#define add_message(msg) add_message_(__LINE__,msg);static void add_message_(int line, const struct recvd_message *msg){ struct recvd_message *seq;
EnterCriticalSection( &sequence_cs ); if (!sequence) { sequence_size = 10; sequence = HeapAlloc( GetProcessHeap(), 0, sequence_size * sizeof(*sequence) ); } if (sequence_cnt == sequence_size) { sequence_size *= 2; sequence = HeapReAlloc( GetProcessHeap(), 0, sequence, sequence_size * sizeof(*sequence) ); } assert(sequence);
seq = &sequence[sequence_cnt++]; seq->hwnd = msg->hwnd; seq->message = msg->message; seq->flags = msg->flags; seq->wParam = msg->wParam; seq->lParam = msg->lParam; seq->line = line; seq->descr = msg->descr; seq->output[0] = 0; LeaveCriticalSection( &sequence_cs );
if (msg->descr) { if (msg->flags & hook) { static const char * const CBT_code_name[10] = { "HCBT_MOVESIZE", "HCBT_MINMAX", "HCBT_QS", "HCBT_CREATEWND", "HCBT_DESTROYWND", "HCBT_ACTIVATE", "HCBT_CLICKSKIPPED", "HCBT_KEYSKIPPED", "HCBT_SYSCOMMAND", "HCBT_SETFOCUS" }; const char *code_name = (msg->message <= HCBT_SETFOCUS) ? CBT_code_name[msg->message] : "Unknown";
sprintf( seq->output, "%s: hook %d (%s) wp %08lx lp %08lx", msg->descr, msg->message, code_name, msg->wParam, msg->lParam ); } else if (msg->flags & winevent_hook) { sprintf( seq->output, "%s: winevent %p %08x %08lx %08lx", msg->descr, msg->hwnd, msg->message, msg->wParam, msg->lParam ); } else { switch (msg->message) { case WM_WINDOWPOSCHANGING: case WM_WINDOWPOSCHANGED: { WINDOWPOS *winpos = (WINDOWPOS *)msg->lParam;
sprintf( seq->output, "%s: %p WM_WINDOWPOS%s wp %08lx lp %08lx after %p x %d y %d cx %d cy %d flags %s", msg->descr, msg->hwnd, (msg->message == WM_WINDOWPOSCHANGING) ? "CHANGING" : "CHANGED", msg->wParam, msg->lParam, winpos->hwndInsertAfter, winpos->x, winpos->y, winpos->cx, winpos->cy, get_winpos_flags(winpos->flags) );
/* Log only documented flags, win2k uses 0x1000 and 0x2000 * in the high word for internal purposes */ seq->wParam = winpos->flags & 0xffff; /* We are not interested in the flags that don't match under XP and Win9x */ seq->wParam &= ~SWP_NOZORDER; break; }
case WM_DRAWITEM: { DRAW_ITEM_STRUCT di; DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)msg->lParam;
sprintf( seq->output, "%s: %p WM_DRAWITEM: type %x, ctl_id %x, item_id %x, action %x, state %x", msg->descr, msg->hwnd, dis->CtlType, dis->CtlID, dis->itemID, dis->itemAction, dis->itemState);
di.u.lp = 0; di.u.item.type = dis->CtlType; di.u.item.ctl_id = dis->CtlID; if (dis->CtlType == ODT_LISTBOX || dis->CtlType == ODT_COMBOBOX || dis->CtlType == ODT_MENU) di.u.item.item_id = dis->itemID; di.u.item.action = dis->itemAction; di.u.item.state = dis->itemState;
seq->lParam = di.u.lp; break; }
case WM_MEASUREITEM: { MEASURE_ITEM_STRUCT mi; MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *)msg->lParam; BOOL is_unicode_data = TRUE;
sprintf( seq->output, "%s: %p WM_MEASUREITEM: CtlType %#x, CtlID %#x, itemID %#x, itemData %#lx", msg->descr, msg->hwnd, mis->CtlType, mis->CtlID, mis->itemID, mis->itemData);
if (mis->CtlType == ODT_LISTBOX) { HWND ctrl = GetDlgItem(msg->hwnd, mis->CtlID); is_unicode_data = GetWindowLongA(ctrl, GWL_STYLE) & LBS_HASSTRINGS; }
mi.u.wp = 0; mi.u.item.CtlType = mis->CtlType; mi.u.item.CtlID = mis->CtlID; mi.u.item.itemID = mis->itemID; mi.u.item.wParam = msg->wParam; seq->wParam = mi.u.wp; if (is_unicode_data) seq->lParam = mis->itemData ? hash_Ly_W((const WCHAR *)mis->itemData) : 0; else seq->lParam = mis->itemData ? hash_Ly((const char *)mis->itemData) : 0; break; }
case WM_COMPAREITEM: { COMPAREITEMSTRUCT *cis = (COMPAREITEMSTRUCT *)msg->lParam; HWND ctrl = GetDlgItem(msg->hwnd, cis->CtlID); BOOL is_unicode_data = TRUE;
ok(msg->wParam == cis->CtlID, "expected %#x, got %#lx\n", cis->CtlID, msg->wParam); ok(cis->hwndItem == ctrl, "expected %p, got %p\n", ctrl, cis->hwndItem); ok((int)cis->itemID1 >= 0, "expected >= 0, got %d\n", cis->itemID1); ok((int)cis->itemID2 == -1, "expected -1, got %d\n", cis->itemID2);
sprintf( seq->output, "%s: %p WM_COMPAREITEM: CtlType %#x, CtlID %#x, itemID1 %#x, itemData1 %#lx, itemID2 %#x, itemData2 %#lx", msg->descr, msg->hwnd, cis->CtlType, cis->CtlID, cis->itemID1, cis->itemData1, cis->itemID2, cis->itemData2);
if (cis->CtlType == ODT_LISTBOX) is_unicode_data = GetWindowLongA(ctrl, GWL_STYLE) & LBS_HASSTRINGS;
if (is_unicode_data) { seq->wParam = cis->itemData1 ? hash_Ly_W((const WCHAR *)cis->itemData1) : 0; seq->lParam = cis->itemData2 ? hash_Ly_W((const WCHAR *)cis->itemData2) : 0; } else { seq->wParam = cis->itemData1 ? hash_Ly((const char *)cis->itemData1) : 0; seq->lParam = cis->itemData2 ? hash_Ly((const char *)cis->itemData2) : 0; } break; }
default: if (msg->message >= 0xc000) return; /* ignore registered messages */ sprintf( seq->output, "%s: %p %04x wp %08lx lp %08lx", msg->descr, msg->hwnd, msg->message, msg->wParam, msg->lParam ); } if (msg->flags & (sent|posted|parent|defwinproc|beginpaint)) sprintf( seq->output + strlen(seq->output), " (flags %x)", msg->flags ); } }}
/* try to make sure pending X events have been processed before continuing */static void flush_events(void){ MSG msg; int diff = 200; int min_timeout = 100; DWORD time = GetTickCount() + diff;
while (diff > 0) { if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break; while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); diff = time - GetTickCount(); }}
static void flush_sequence(void){ EnterCriticalSection( &sequence_cs ); HeapFree(GetProcessHeap(), 0, sequence); sequence = 0; sequence_cnt = sequence_size = 0; LeaveCriticalSection( &sequence_cs );}
static void dump_sequence(const struct message *expected, const char *context, const char *file, int line){ const struct recvd_message *actual = sequence; unsigned int count = 0;
trace_(file, line)("Failed sequence %s:\n", context ); while (expected->message && actual->message) { if (actual->output[0]) { if (expected->flags & hook) { trace_(file, line)( " %u: expected: hook %04x - actual: %s\n", count, expected->message, actual->output ); } else if (expected->flags & winevent_hook) { trace_(file, line)( " %u: expected: winevent %04x - actual: %s\n", count, expected->message, actual->output ); } else if (expected->flags & kbd_hook) { trace_(file, line)( " %u: expected: kbd %04x - actual: %s\n", count, expected->message, actual->output ); } else { trace_(file, line)( " %u: expected: msg %04x - actual: %s\n", count, expected->message, actual->output ); } }
if (expected->message == actual->message) { if ((expected->flags & defwinproc) != (actual->flags & defwinproc) && (expected->flags & optional)) { /* don't match messages if their defwinproc status differs */ expected++; } else { expected++; actual++; } } /* silently drop winevent messages if there is no support for them */ else if ((expected->flags & optional) || ((expected->flags & winevent_hook) && !hEvent_hook)) expected++; else { expected++; actual++; } count++; }
/* optional trailing messages */ while (expected->message && ((expected->flags & optional) || ((expected->flags & winevent_hook) && !hEvent_hook))) { trace_(file, line)( " %u: expected: msg %04x - actual: nothing\n", count, expected->message ); expected++; count++; }
if (expected->message) { trace_(file, line)( " %u: expected: msg %04x - actual: nothing\n", count, expected->message ); return; }
while (actual->message && actual->output[0]) { trace_(file, line)( " %u: expected: nothing - actual: %s\n", count, actual->output ); actual++; count++; }}
#define ok_sequence( exp, contx, todo) \ ok_sequence_( (exp), (contx), (todo), __FILE__, __LINE__)
static void ok_sequence_(const struct message *expected_list, const char *context, BOOL todo, const char *file, int line){ static const struct recvd_message end_of_sequence; const struct message *expected = expected_list; const struct recvd_message *actual; int failcount = 0, dump = 0; unsigned int count = 0;
add_message(&end_of_sequence);
actual = sequence;
while (expected->message && actual->message) { if (expected->message == actual->message && !((expected->flags ^ actual->flags) & (hook|winevent_hook|kbd_hook))) { if (expected->flags & wparam) { if (((expected->wParam ^ actual->wParam) & ~expected->wp_mask) && todo) { todo_wine { failcount ++; if (strcmp(winetest_platform, "wine")) dump++; ok_( file, line) (FALSE, "%s: %u: in msg 0x%04x expecting wParam 0x%lx got 0x%lx\n", context, count, expected->message, expected->wParam, actual->wParam); } } else { ok_( file, line)( ((expected->wParam ^ actual->wParam) & ~expected->wp_mask) == 0, "%s: %u: in msg 0x%04x expecting wParam 0x%lx got 0x%lx\n", context, count, expected->message, expected->wParam, actual->wParam); if ((expected->wParam ^ actual->wParam) & ~expected->wp_mask) dump++; }
} if (expected->flags & lparam) { if (((expected->lParam ^ actual->lParam) & ~expected->lp_mask) && todo) { todo_wine { failcount ++; if (strcmp(winetest_platform, "wine")) dump++; ok_( file, line) (FALSE, "%s: %u: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n", context, count, expected->message, expected->lParam, actual->lParam); } } else { ok_( file, line)(((expected->lParam ^ actual->lParam) & ~expected->lp_mask) == 0, "%s: %u: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n", context, count, expected->message, expected->lParam, actual->lParam); if ((expected->lParam ^ actual->lParam) & ~expected->lp_mask) dump++; } } if ((expected->flags & optional) && ((expected->flags ^ actual->flags) & (defwinproc|parent))) { /* don't match optional messages if their defwinproc or parent status differs */ expected++; count++; continue; } if ((expected->flags & defwinproc) != (actual->flags & defwinproc) && todo) { todo_wine { failcount ++; if (strcmp(winetest_platform, "wine")) dump++; ok_( file, line) (FALSE, "%s: %u: the msg 0x%04x should %shave been sent by DefWindowProc\n", context, count, expected->message, (expected->flags & defwinproc) ? "" : "NOT "); } } else { ok_( file, line) ((expected->flags & defwinproc) == (actual->flags & defwinproc), "%s: %u: the msg 0x%04x should %shave been sent by DefWindowProc\n", context, count, expected->message, (expected->flags & defwinproc) ? "" : "NOT "); if ((expected->flags & defwinproc) != (actual->flags & defwinproc)) dump++; }
ok_( file, line) ((expected->flags & beginpaint) == (actual->flags & beginpaint), "%s: %u: the msg 0x%04x should %shave been sent by BeginPaint\n", context, count, expected->message, (expected->flags & beginpaint) ? "" : "NOT "); if ((expected->flags & beginpaint) != (actual->flags & beginpaint)) dump++;
ok_( file, line) ((expected->flags & (sent|posted)) == (actual->flags & (sent|posted)), "%s: %u: the msg 0x%04x should have been %s\n", context, count, expected->message, (expected->flags & posted) ? "posted" : "sent"); if ((expected->flags & (sent|posted)) != (actual->flags & (sent|posted))) dump++;
ok_( file, line) ((expected->flags & parent) == (actual->flags & parent), "%s: %u: the msg 0x%04x was expected in %s\n", context, count, expected->message, (expected->flags & parent) ? "parent" : "child"); if ((expected->flags & parent) != (actual->flags & parent)) dump++;
ok_( file, line) ((expected->flags & hook) == (actual->flags & hook), "%s: %u: the msg 0x%04x should have been sent by a hook\n", context, count, expected->message); if ((expected->flags & hook) != (actual->flags & hook)) dump++;
ok_( file, line) ((expected->flags & winevent_hook) == (actual->flags & winevent_hook), "%s: %u: the msg 0x%04x should have been sent by a winevent hook\n", context, count, expected->message); if ((expected->flags & winevent_hook) != (actual->flags & winevent_hook)) dump++;
ok_( file, line) ((expected->flags & kbd_hook) == (actual->flags & kbd_hook), "%s: %u: the msg 0x%04x should have been sent by a keyboard hook\n", context, count, expected->message); if ((expected->flags & kbd_hook) != (actual->flags & kbd_hook)) dump++;
expected++; actual++; } /* silently drop hook messages if there is no support for them */ else if ((expected->flags & optional) || ((expected->flags & hook) && !hCBT_hook) || ((expected->flags & winevent_hook) && !hEvent_hook) || ((expected->flags & kbd_hook) && !hKBD_hook)) expected++; else if (todo) { failcount++; todo_wine { if (strcmp(winetest_platform, "wine")) dump++; ok_( file, line) (FALSE, "%s: %u: the msg 0x%04x was expected, but got msg 0x%04x instead\n", context, count, expected->message, actual->message); } goto done; } else { ok_( file, line) (FALSE, "%s: %u: the msg 0x%04x was expected, but got msg 0x%04x instead\n", context, count, expected->message, actual->message); dump++; expected++; actual++; } count++; }
/* skip all optional trailing messages */ while (expected->message && ((expected->flags & optional) || ((expected->flags & hook) && !hCBT_hook) || ((expected->flags & winevent_hook) && !hEvent_hook))) expected++;
if (todo) { todo_wine { if (expected->message || actual->message) { failcount++; if (strcmp(winetest_platform, "wine")) dump++; ok_( file, line) (FALSE, "%s: %u: the msg sequence is not complete: expected %04x - actual %04x\n", context, count, expected->message, actual->message); } } } else { if (expected->message || actual->message) { dump++; ok_( file, line) (FALSE, "%s: %u: the msg sequence is not complete: expected %04x - actual %04x\n", context, count, expected->message, actual->message); } } if( todo && !failcount) /* succeeded yet marked todo */ todo_wine { if (!strcmp(winetest_platform, "wine")) dump++; ok_( file, line)( TRUE, "%s: marked \"todo_wine\" but succeeds\n", context); }
done: if (dump) dump_sequence(expected_list, context, file, line); flush_sequence();}
#define expect(EXPECTED,GOT) ok((GOT)==(EXPECTED), "Expected %d, got %d\n", (EXPECTED), (GOT))
/******************************** MDI test **********************************/
/* CreateWindow for MDI frame window, initially visible */static const struct message WmCreateMDIframeSeq[] = { { HCBT_CREATEWND, hook }, { WM_GETMINMAXINFO, sent }, { WM_NCCREATE, sent }, { WM_NCCALCSIZE, sent|wparam, 0 }, { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, { WM_CREATE, sent }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, { WM_NOTIFYFORMAT, sent|optional }, { WM_QUERYUISTATE, sent|optional }, { WM_WINDOWPOSCHANGING, sent|optional }, { WM_GETMINMAXINFO, sent|optional }, { WM_NCCALCSIZE, sent|optional }, { WM_WINDOWPOSCHANGED, sent|optional }, { WM_SHOWWINDOW, sent|wparam, 1 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { HCBT_ACTIVATE, hook }, { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* XP */ { WM_ACTIVATEAPP, sent|wparam|optional, 1 }, /* Win9x doesn't send it */ { WM_NCACTIVATE, sent }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ACTIVATE, sent|wparam, 1 }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* Win9x */ { HCBT_SETFOCUS, hook }, { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, /* Win9x adds SWP_NOZORDER below */ { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* XP */ { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SIZE, sent|wparam, SIZE_RESTORED }, { WM_MOVE, sent }, { 0 }};/* DestroyWindow for MDI frame window, initially visible */static const struct message WmDestroyMDIframeSeq[] = { { HCBT_DESTROYWND, hook }, { 0x0090, sent|optional }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, { WM_NCACTIVATE, sent|wparam|optional, 0 }, /* Win9x */ { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { WM_NCACTIVATE, sent|wparam|optional, 0 }, /* XP */ { WM_ACTIVATE, sent|wparam|optional, 0 }, /* Win9x */ { WM_ACTIVATEAPP, sent|wparam|optional, 0 }, /* Win9x */ { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, { WM_DESTROY, sent }, { WM_NCDESTROY, sent }, { 0 }};/* CreateWindow for MDI client window, initially visible */static const struct message WmCreateMDIclientSeq[] = { { HCBT_CREATEWND, hook }, { WM_NCCREATE, sent }, { WM_NCCALCSIZE, sent|wparam, 0 }, { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|optional, 0, 0 }, { WM_CREATE, sent }, { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|optional, 0, 0 }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SIZE, sent|wparam, SIZE_RESTORED }, { WM_MOVE, sent }, { WM_PARENTNOTIFY, sent|wparam, WM_CREATE }, /* in MDI frame */ { WM_SHOWWINDOW, sent|wparam, 1 }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { 0 }};/* ShowWindow(SW_SHOW) for MDI client window */static const struct message WmShowMDIclientSeq[] = { { WM_SHOWWINDOW, sent|wparam, 1 }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { 0 }};/* ShowWindow(SW_HIDE) for MDI client window */static const struct message WmHideMDIclientSeq[] = { { WM_SHOWWINDOW, sent|wparam, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam|optional, 0, 0 }, /* win2000 */ { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP */ { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { 0 }};/* DestroyWindow for MDI client window, initially visible */static const struct message WmDestroyMDIclientSeq[] = { { HCBT_DESTROYWND, hook }, { 0x0090, sent|optional }, { WM_PARENTNOTIFY, sent|wparam, WM_DESTROY }, /* in MDI frame */ { WM_SHOWWINDOW, sent|wparam, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, { WM_DESTROY, sent }, { WM_NCDESTROY, sent }, { 0 }};/* CreateWindow for MDI child window, initially visible */static const struct message WmCreateMDIchildVisibleSeq[] = { { HCBT_CREATEWND, hook }, { WM_NCCREATE, sent }, { WM_NCCALCSIZE, sent|wparam, 0 }, { WM_CREATE, sent }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SIZE, sent|wparam, SIZE_RESTORED }, { WM_MOVE, sent }, /* Win2k sends wparam set to * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated), * while Win9x doesn't bother to set child window id according to * CLIENTCREATESTRUCT.idFirstChild */ { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */ { WM_SHOWWINDOW, sent|wparam, 1 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
/* Win9x: message sequence terminates here. */
{ WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, { HCBT_SETFOCUS, hook }, /* in MDI client */ { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ { WM_IME_NOTIFY, sent|wparam|optional, 2 }, /* in MDI client */ { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent }, /* in MDI client */ { HCBT_SETFOCUS, hook }, { WM_KILLFOCUS, sent }, /* in MDI client */ { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|defwinproc }, { WM_MDIACTIVATE, sent|defwinproc }, { 0 }};/* WM_CHILDACTIVATE sent to disabled window */static const struct message WmChildActivateDisabledWindowSeq[] = { { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, { 0 }};/* WM_CHILDACTIVATE sent to enabled window */static const struct message WmChildActivateWindowSeq[] = { { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, { WM_MDIACTIVATE, sent|defwinproc }, { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, { HCBT_SETFOCUS, hook }, { WM_KILLFOCUS, sent|defwinproc }, { WM_SETFOCUS, sent }, { HCBT_SETFOCUS, hook }, { WM_KILLFOCUS, sent }, { WM_SETFOCUS, sent|defwinproc }, { WM_MDIACTIVATE, sent|defwinproc }, { 0 }};/* CreateWindow for MDI child window with invisible parent */static const struct message WmCreateMDIchildInvisibleParentSeq[] = { { HCBT_CREATEWND, hook }, { WM_GETMINMAXINFO, sent }, { WM_NCCREATE, sent }, { WM_NCCALCSIZE, sent|wparam, 0 }, { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam|optional, 0, 0 }, { WM_CREATE, sent }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SIZE, sent|wparam, SIZE_RESTORED }, { WM_MOVE, sent }, { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */ { WM_SHOWWINDOW, sent|wparam, 1 }, { WM_MDIREFRESHMENU, sent }, /* in MDI client */ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
/* Win9x: message sequence terminates here. */
{ WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, { HCBT_SETFOCUS, hook }, /* in MDI client */ { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ { WM_IME_NOTIFY, sent|wparam|optional, 2 }, /* in MDI client */ { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent }, /* in MDI client */ { HCBT_SETFOCUS, hook }, { WM_KILLFOCUS, sent }, /* in MDI client */ { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|defwinproc }, { WM_MDIACTIVATE, sent|defwinproc }, { 0 }};/* DestroyWindow for MDI child window, initially visible */static const struct message WmDestroyMDIchildVisibleSeq[] = { { HCBT_DESTROYWND, hook }, /* Win2k sends wparam set to * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated), * while Win9x doesn't bother to set child window id according to * CLIENTCREATESTRUCT.idFirstChild */ { 0x0090, sent|optional }, { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */ { WM_SHOWWINDOW, sent|wparam, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, { WM_ERASEBKGND, sent|parent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
/* { WM_DESTROY, sent } * Win9x: message sequence terminates here. */
{ HCBT_SETFOCUS, hook }, /* set focus to MDI client */ { WM_KILLFOCUS, sent }, { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent }, /* in MDI client */
{ HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */ { WM_KILLFOCUS, sent }, /* in MDI client */ { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent }, /* in MDI client */
{ EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
{ HCBT_SETFOCUS, hook }, /* set focus to MDI client */ { WM_KILLFOCUS, sent }, { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent }, /* in MDI client */
{ HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */ { WM_KILLFOCUS, sent }, /* in MDI client */ { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent }, /* in MDI client */
{ WM_DESTROY, sent },
{ HCBT_SETFOCUS, hook }, /* set focus to MDI client */ { WM_KILLFOCUS, sent }, { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent }, /* in MDI client */
{ HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */ { WM_KILLFOCUS, sent }, /* in MDI client */ { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent }, /* in MDI client */
{ WM_NCDESTROY, sent }, { 0 }};/* CreateWindow for MDI child window, initially invisible */static const struct message WmCreateMDIchildInvisibleSeq[] = { { HCBT_CREATEWND, hook }, { WM_NCCREATE, sent }, { WM_NCCALCSIZE, sent|wparam, 0 }, { WM_CREATE, sent }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SIZE, sent|wparam, SIZE_RESTORED }, { WM_MOVE, sent }, /* Win2k sends wparam set to * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated), * while Win9x doesn't bother to set child window id according to * CLIENTCREATESTRUCT.idFirstChild */ { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */ { 0 }};/* DestroyWindow for MDI child window, initially invisible */static const struct message WmDestroyMDIchildInvisibleSeq[] = { { HCBT_DESTROYWND, hook }, /* Win2k sends wparam set to * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated), * while Win9x doesn't bother to set child window id according to * CLIENTCREATESTRUCT.idFirstChild */ { 0x0090, sent|optional }, { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */ { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, { WM_DESTROY, sent }, { WM_NCDESTROY, sent }, /* FIXME: Wine destroys an icon/title window while Windows doesn't */ { WM_PARENTNOTIFY, sent|wparam|optional, WM_DESTROY }, /* MDI client */ { 0 }};/* CreateWindow for the 1st MDI child window, initially visible and maximized */static const struct message WmCreateMDIchildVisibleMaxSeq1[] = { { HCBT_CREATEWND, hook }, { WM_NCCREATE, sent }, { WM_NCCALCSIZE, sent|wparam, 0 }, { WM_CREATE, sent }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SIZE, sent|wparam, SIZE_RESTORED }, { WM_MOVE, sent }, { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, { WM_GETMINMAXINFO, sent }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_STATECHANGED }, { WM_NCCALCSIZE, sent|wparam, 1 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, /* in MDI frame */ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCCALCSIZE, sent|wparam, 1 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ /* Win2k sends wparam set to * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated), * while Win9x doesn't bother to set child window id according to * CLIENTCREATESTRUCT.idFirstChild */ { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */ { WM_SHOWWINDOW, sent|wparam, 1 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc|optional, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE, 0, SWP_FRAMECHANGED },
/* Win9x: message sequence terminates here. */
{ WM_NCACTIVATE, sent|wparam|defwinproc|optional, 1 }, { HCBT_SETFOCUS, hook|optional }, /* in MDI client */ { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ { WM_IME_NOTIFY, sent|wparam|optional, 2 }, /* in MDI client */ { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|optional }, /* in MDI client */ { HCBT_SETFOCUS, hook|optional }, { WM_KILLFOCUS, sent|optional }, /* in MDI client */ { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|defwinproc|optional }, { WM_MDIACTIVATE, sent|defwinproc|optional }, /* in MDI frame */ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCCALCSIZE, sent|wparam, 1 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ { 0 }};/* CreateWindow for the 2nd MDI child window, initially visible and maximized */static const struct message WmCreateMDIchildVisibleMaxSeq2[] = { /* restore the 1st MDI child */ { WM_SETREDRAW, sent|wparam, 0 }, { HCBT_MINMAX, hook|lparam, 0, SW_SHOWNORMAL }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, { WM_NCCALCSIZE, sent|wparam, 1 }, { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, /* in MDI frame */ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCCALCSIZE, sent|wparam, 1 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ { WM_SETREDRAW, sent|wparam, 1 }, /* in the 1st MDI child */ /* create the 2nd MDI child */ { HCBT_CREATEWND, hook }, { WM_NCCREATE, sent }, { WM_NCCALCSIZE, sent|wparam, 0 }, { WM_CREATE, sent }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SIZE, sent|wparam, SIZE_RESTORED }, { WM_MOVE, sent }, { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, { WM_GETMINMAXINFO, sent }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_STATECHANGED }, { WM_NCCALCSIZE, sent|wparam, 1 }, { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, /* in MDI frame */ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCCALCSIZE, sent|wparam, 1 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ /* Win2k sends wparam set to * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated), * while Win9x doesn't bother to set child window id according to * CLIENTCREATESTRUCT.idFirstChild */ { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */ { WM_SHOWWINDOW, sent|wparam, 1 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
{ WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 1st MDI child */ { WM_MDIACTIVATE, sent|defwinproc }, /* in the 1st MDI child */
{ WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
/* Win9x: message sequence terminates here. */
{ WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, { HCBT_SETFOCUS, hook }, { WM_KILLFOCUS, sent|defwinproc|optional }, /* in the 1st MDI child */ { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 }, /* in the 1st MDI child */ { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent }, /* in MDI client */ { HCBT_SETFOCUS, hook }, { WM_KILLFOCUS, sent }, /* in MDI client */ { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|defwinproc },
{ WM_MDIACTIVATE, sent|defwinproc }, /* in MDI frame */ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCCALCSIZE, sent|wparam, 1 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ { 0 }};/* WM_MDICREATE MDI child window, initially visible and maximized */static const struct message WmCreateMDIchildVisibleMaxSeq3[] = { { WM_MDICREATE, sent }, { HCBT_CREATEWND, hook }, { WM_NCCREATE, sent }, { WM_NCCALCSIZE, sent|wparam, 0 }, { WM_CREATE, sent }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SIZE, sent|wparam, SIZE_RESTORED }, { WM_MOVE, sent }, { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, { WM_GETMINMAXINFO, sent }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_STATECHANGED }, { WM_NCCALCSIZE, sent|wparam, 1 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED },
/* in MDI frame */ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCCALCSIZE, sent|wparam, 1 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
/* Win2k sends wparam set to * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated), * while Win9x doesn't bother to set child window id according to * CLIENTCREATESTRUCT.idFirstChild */ { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */ { WM_SHOWWINDOW, sent|wparam, 1 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
{ EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
{ WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
{ WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
/* Win9x: message sequence terminates here. */
{ WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, { WM_SETFOCUS, sent|optional }, /* in MDI client */ { HCBT_SETFOCUS, hook }, /* in MDI client */ { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ { WM_IME_NOTIFY, sent|wparam|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|optional }, /* in MDI client */ { HCBT_SETFOCUS, hook|optional }, { WM_KILLFOCUS, sent }, /* in MDI client */ { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|defwinproc },
{ WM_MDIACTIVATE, sent|defwinproc },
/* in MDI child */ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCCALCSIZE, sent|wparam, 1 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
/* in MDI frame */ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCCALCSIZE, sent|wparam, 1 }, { 0x0093, sent|defwinproc|optional }, { 0x0093, sent|defwinproc|optional }, { 0x0093, sent|defwinproc|optional }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED },
/* in MDI client */ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE }, { WM_NCCALCSIZE, sent|wparam, 1 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOCLIENTMOVE }, { WM_SIZE, sent|wparam, SIZE_RESTORED },
/* in MDI child */ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE }, { WM_NCCALCSIZE, sent|wparam, 1 }, { 0x0093, sent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOCLIENTMOVE }, { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED },
{ 0x0093, sent|optional }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */ { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* XP sends it to MDI frame */ { 0x0093, sent|defwinproc|optional }, { 0x0093, sent|defwinproc|optional }, { 0x0093, sent|defwinproc|optional }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* XP sends a duplicate */
{ 0 }};/* CreateWindow for the 1st MDI child window, initially invisible and maximized */static const struct message WmCreateMDIchildInvisibleMaxSeq4[] = { { HCBT_CREATEWND, hook }, { WM_GETMINMAXINFO, sent }, { WM_NCCREATE, sent }, { WM_NCCALCSIZE, sent|wparam, 0 }, { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, { WM_CREATE, sent }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SIZE, sent|wparam, SIZE_RESTORED }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE, 0, SWP_NOZORDER }, /* MDI frame */ { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* MDI frame */ { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE, 0, SWP_NOZORDER }, /* MDI frame */ { WM_MOVE, sent }, { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, { WM_GETMINMAXINFO, sent }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_STATECHANGED }, { WM_GETMINMAXINFO, sent|defwinproc }, { WM_NCCALCSIZE, sent|wparam, 1 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOREDRAW|SWP_STATECHANGED }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, /* in MDI frame */ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCCALCSIZE, sent|wparam, 1 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* MDI child */ { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ /* Win2k sends wparam set to * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated), * while Win9x doesn't bother to set child window id according to * CLIENTCREATESTRUCT.idFirstChild */ { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */ { 0 }};/* WM_SYSCOMMAND/SC_CLOSE for the 2nd MDI child window, initially visible and maximized */static const struct message WmDestroyMDIchildVisibleMaxSeq2[] = { { WM_SYSCOMMAND, sent|wparam, SC_CLOSE }, { HCBT_SYSCOMMAND, hook }, { WM_CLOSE, sent|defwinproc }, { WM_MDIDESTROY, sent }, /* in MDI client */
/* bring the 1st MDI child to top */ { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOSIZE|SWP_NOMOVE }, /* in the 1st MDI child */ { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, /* in the 2nd MDI child */
{ EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
{ WM_CHILDACTIVATE, sent|defwinproc|wparam|lparam, 0, 0 }, /* in the 1st MDI child */ { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 1st MDI child */ { WM_MDIACTIVATE, sent|defwinproc }, /* in the 1st MDI child */
/* maximize the 1st MDI child */ { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, { WM_GETMINMAXINFO, sent|defwinproc }, { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_STATECHANGED }, { WM_NCCALCSIZE, sent|defwinproc|wparam, 1 }, { WM_CHILDACTIVATE, sent|defwinproc|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED },
/* restore the 2nd MDI child */ { WM_SETREDRAW, sent|defwinproc|wparam, 0 }, { HCBT_MINMAX, hook|lparam, 0, SW_NORMALNA }, { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_SHOWWINDOW|SWP_STATECHANGED }, { WM_NCCALCSIZE, sent|defwinproc|wparam, 1 },
{ EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
{ WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED },
{ EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
{ WM_SETREDRAW, sent|defwinproc|wparam, 1 }, /* in MDI frame */ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCCALCSIZE, sent|wparam, 1 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
/* bring the 1st MDI child to top */ { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, { HCBT_SETFOCUS, hook }, { WM_KILLFOCUS, sent|defwinproc }, { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 }, { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent }, /* in MDI client */ { HCBT_SETFOCUS, hook }, { WM_KILLFOCUS, sent }, /* in MDI client */ { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|defwinproc }, { WM_MDIACTIVATE, sent|defwinproc }, { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
/* apparently ShowWindow(SW_SHOW) on an MDI client */ { WM_SHOWWINDOW, sent|wparam, 1 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { WM_MDIREFRESHMENU, sent },
{ HCBT_DESTROYWND, hook }, /* Win2k sends wparam set to * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated), * while Win9x doesn't bother to set child window id according to * CLIENTCREATESTRUCT.idFirstChild */ { 0x0090, sent|defwinproc|optional }, { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */ { WM_SHOWWINDOW, sent|defwinproc|wparam, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, { WM_ERASEBKGND, sent|parent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
{ EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, { WM_DESTROY, sent|defwinproc }, { WM_NCDESTROY, sent|defwinproc }, { 0 }};/* WM_MDIDESTROY for the single MDI child window, initially visible and maximized */static const struct message WmDestroyMDIchildVisibleMaxSeq1[] = { { WM_MDIDESTROY, sent }, /* in MDI client */ { WM_SHOWWINDOW, sent|wparam, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, { WM_ERASEBKGND, sent|parent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
{ HCBT_SETFOCUS, hook }, { WM_KILLFOCUS, sent }, { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent }, /* in MDI client */ { HCBT_SETFOCUS, hook }, { WM_KILLFOCUS, sent }, /* in MDI client */ { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent },
/* in MDI child */ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCCALCSIZE, sent|wparam, 1 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
/* in MDI frame */ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCCALCSIZE, sent|wparam, 1 }, { 0x0093, sent|defwinproc|optional }, { 0x0093, sent|defwinproc|optional }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED },
/* in MDI client */ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE }, { WM_NCCALCSIZE, sent|wparam, 1 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOCLIENTMOVE }, { WM_SIZE, sent|wparam, SIZE_RESTORED },
/* in MDI child */ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE }, { WM_NCCALCSIZE, sent|wparam, 1 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE }, { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED },
/* in MDI child */ { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 }, { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
/* in MDI frame */ { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 }, { 0x0093, sent|defwinproc|optional }, { 0x0093, sent|defwinproc|optional }, { 0x0093, sent|defwinproc|optional }, { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED },
/* in MDI client */ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE }, { WM_NCCALCSIZE, sent|wparam, 1 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOCLIENTMOVE }, { WM_SIZE, sent|wparam, SIZE_RESTORED },
/* in MDI child */ { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE }, { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 }, { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE }, { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */
{ 0x0093, sent|defwinproc|optional }, { WM_NCCALCSIZE, sent|wparam|defwinproc|optional, 1 }, /* XP sends it to MDI frame */ { 0x0093, sent|defwinproc|optional }, { 0x0093, sent|defwinproc|optional }, { 0x0093, sent|defwinproc|optional }, { 0x0093, sent|optional },
{ EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */ { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* XP sends a duplicate */
/* in MDI frame */ { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCCALCSIZE, sent|wparam|optional, 1 }, { 0x0093, sent|defwinproc|optional }, { 0x0093, sent|defwinproc|optional }, { 0x0093, sent|defwinproc|optional }, { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ { 0x0093, sent|optional },
{ WM_NCACTIVATE, sent|wparam, 0 }, { WM_MDIACTIVATE, sent },
{ HCBT_MINMAX, hook|lparam, 0, SW_SHOWNORMAL }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_SHOWWINDOW|SWP_STATECHANGED }, { WM_NCCALCSIZE, sent|wparam, 1 },
{ EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
{ WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED },
/* in MDI child */ { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 }, { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
/* in MDI frame */ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCCALCSIZE, sent|wparam, 1 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED },
/* in MDI client */ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE }, { WM_NCCALCSIZE, sent|wparam, 1 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOCLIENTMOVE }, { WM_SIZE, sent|wparam, SIZE_RESTORED }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* XP */ { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */ { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* XP sends a duplicate */
{ HCBT_SETFOCUS, hook }, { WM_KILLFOCUS, sent }, { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent }, /* in MDI client */
{ WM_MDIREFRESHMENU, sent }, /* in MDI client */
{ HCBT_DESTROYWND, hook }, /* Win2k sends wparam set to * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated), * while Win9x doesn't bother to set child window id according to * CLIENTCREATESTRUCT.idFirstChild */ { 0x0090, sent|optional }, { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
{ WM_SHOWWINDOW, sent|wparam, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, { WM_ERASEBKGND, sent|parent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
{ EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, { WM_DESTROY, sent }, { WM_NCDESTROY, sent }, { 0 }};/* ShowWindow(SW_MAXIMIZE) for a not visible MDI child window */static const struct message WmMaximizeMDIchildInvisibleSeq[] = { { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, { WM_GETMINMAXINFO, sent }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_STATECHANGED }, { WM_NCCALCSIZE, sent|wparam, 1 }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
{ WM_WINDOWPOSCHANGING, sent|wparam|optional|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCACTIVATE, sent|wparam|optional|defwinproc, 1 }, { HCBT_SETFOCUS, hook|optional }, { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|optional }, /* in MDI client */ { HCBT_SETFOCUS, hook|optional }, { WM_KILLFOCUS, sent|optional }, /* in MDI client */ { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|optional|defwinproc }, { WM_MDIACTIVATE, sent|optional|defwinproc }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, /* in MDI frame */ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCCALCSIZE, sent|wparam, 1 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ { 0 }};/* ShowWindow(SW_MAXIMIZE) for a not visible maximized MDI child window */static const struct message WmMaximizeMDIchildInvisibleSeq2[] = { { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, { WM_GETMINMAXINFO, sent }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED }, { WM_GETMINMAXINFO, sent|defwinproc }, { WM_NCCALCSIZE, sent|wparam, 1 }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
{ WM_WINDOWPOSCHANGING, sent|wparam|defwinproc|optional, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCACTIVATE, sent|wparam|defwinproc|optional, 1 }, { HCBT_SETFOCUS, hook|optional }, { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|optional }, /* in MDI client */ { HCBT_SETFOCUS, hook|optional }, { WM_KILLFOCUS, sent|optional }, /* in MDI client */ { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|defwinproc|optional }, { WM_MDIACTIVATE, sent|defwinproc|optional }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ { WM_SIZE, sent|defwinproc|optional }, { 0 }};/* WM_MDIMAXIMIZE for an MDI child window with invisible parent */static const struct message WmMaximizeMDIchildInvisibleParentSeq[] = { { WM_MDIMAXIMIZE, sent }, /* in MDI client */ { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, { WM_GETMINMAXINFO, sent }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, { WM_GETMINMAXINFO, sent|defwinproc }, { WM_NCCALCSIZE, sent|wparam, 1 }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP doesn't send it */ { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOREDRAW|SWP_STATECHANGED }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED },
{ WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 }, { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { WM_NCCALCSIZE, sent|wparam|defwinproc|optional, 1 }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI child XP */ { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI client XP */ /* in MDI frame */ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCCALCSIZE, sent|wparam, 1 }, { 0x0093, sent|defwinproc|optional }, { 0x0094, sent|defwinproc|optional }, { 0x0094, sent|defwinproc|optional }, { 0x0094, sent|defwinproc|optional }, { 0x0094, sent|defwinproc|optional }, { 0x0093, sent|defwinproc|optional }, { 0x0093, sent|defwinproc|optional }, { 0x0091, sent|defwinproc|optional }, { 0x0092, sent|defwinproc|optional }, { 0x0092, sent|defwinproc|optional }, { 0x0092, sent|defwinproc|optional }, { 0x0092, sent|defwinproc|optional }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI frame win2000 */ /* in MDI client */ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE }, { WM_NCCALCSIZE, sent|wparam, 1 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE }, { WM_SIZE, sent|wparam, SIZE_RESTORED }, /* in MDI child */ { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE }, { WM_GETMINMAXINFO, sent|defwinproc }, { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 }, { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE }, { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI child win2000 */ { WM_NCCALCSIZE, sent|wparam|defwinproc|optional, 1 }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI child XP */ { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI child XP */ { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI client XP */ /* in MDI frame */ { 0x0093, sent|optional }, { WM_NCCALCSIZE, sent|wparam|optional, 1 }, { 0x0093, sent|defwinproc|optional }, { 0x0093, sent|defwinproc|optional }, { 0x0093, sent|defwinproc|optional }, { 0x0091, sent|defwinproc|optional }, { 0x0092, sent|defwinproc|optional }, { 0x0092, sent|defwinproc|optional }, { 0x0092, sent|defwinproc|optional }, { 0x0092, sent|defwinproc|optional }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI frame XP */ { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI frame XP */ { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* MDI child XP */ { 0 }};/* ShowWindow(SW_MAXIMIZE) for a visible MDI child window */static const struct message WmMaximizeMDIchildVisibleSeq[] = { { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, { WM_GETMINMAXINFO, sent }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, { WM_NCCALCSIZE, sent|wparam, 1 }, { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, /* in MDI frame */ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCCALCSIZE, sent|wparam, 1 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ { 0 }};/* ShowWindow(SW_RESTORE) for a visible maximized MDI child window */static const struct message WmRestoreMDIchildVisibleSeq[] = { { HCBT_MINMAX, hook|lparam, 0, SW_RESTORE }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, { WM_NCCALCSIZE, sent|wparam, 1 }, { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, /* in MDI frame */ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCCALCSIZE, sent|wparam, 1 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ { 0 }};/* ShowWindow(SW_RESTORE) for a visible minimized MDI child window */static const struct message WmRestoreMDIchildVisibleSeq_2[] = { { HCBT_MINMAX, hook|lparam, 0, SW_RESTORE }, { WM_QUERYOPEN, sent|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, { WM_NCCALCSIZE, sent|wparam, 1 }, { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ { EVENT_SYSTEM_MINIMIZEEND, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ { HCBT_SETFOCUS, hook }, { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent }, { 0 }};/* ShowWindow(SW_MINIMIZE) for a visible restored MDI child window */static const struct message WmMinimizeMDIchildVisibleSeq[] = { { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_STATECHANGED }, { WM_NCCALCSIZE, sent|wparam, 1 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_STATECHANGED }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|defwinproc|wparam|lparam, SIZE_MINIMIZED, 0 }, { WM_CHILDACTIVATE, sent|wparam|lparam|defwinproc, 0, 0 }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ /* FIXME: Wine creates an icon/title window while Windows doesn't */ { WM_PARENTNOTIFY, sent|parent|wparam|optional, WM_CREATE }, /* MDI client */ { 0 }};/* ShowWindow(SW_RESTORE) for a not visible MDI child window */static const struct message WmRestoreMDIchildInvisibleSeq[] = { { HCBT_MINMAX, hook|lparam, 0, SW_RESTORE }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_STATECHANGED }, { WM_NCCALCSIZE, sent|wparam, 1 }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, /* in MDI frame */ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCCALCSIZE, sent|wparam, 1 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ { 0 }};
static HWND mdi_client;static WNDPROC old_mdi_client_proc;
static LRESULT WINAPI mdi_client_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ struct recvd_message msg;
/* do not log painting messages */ if (message != WM_PAINT && message != WM_NCPAINT && message != WM_SYNCPAINT && message != WM_ERASEBKGND && message != WM_NCHITTEST && message != WM_GETTEXT && message != WM_MDIGETACTIVE && !ignore_message( message )) { msg.hwnd = hwnd; msg.message = message; msg.flags = sent|wparam|lparam; msg.wParam = wParam; msg.lParam = lParam; msg.descr = "mdi client"; add_message(&msg); }
return CallWindowProcA(old_mdi_client_proc, hwnd, message, wParam, lParam);}
static LRESULT WINAPI mdi_child_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ static LONG defwndproc_counter = 0; LRESULT ret; struct recvd_message msg;
/* do not log painting messages */ if (message != WM_PAINT && message != WM_NCPAINT && message != WM_SYNCPAINT && message != WM_ERASEBKGND && message != WM_NCHITTEST && message != WM_GETTEXT && !ignore_message( message )) { switch (message) { case WM_MDIACTIVATE: { HWND active, client = GetParent(hwnd);
active = (HWND)SendMessageA(client, WM_MDIGETACTIVE, 0, 0);
if (hwnd == (HWND)lParam) /* if we are being activated */ ok (active == (HWND)lParam, "new active %p != active %p\n", (HWND)lParam, active); else ok (active == (HWND)wParam, "old active %p != active %p\n", (HWND)wParam, active); break; } }
msg.hwnd = hwnd; msg.message = message; msg.flags = sent|wparam|lparam; if (defwndproc_counter) msg.flags |= defwinproc; msg.wParam = wParam; msg.lParam = lParam; msg.descr = "mdi child"; add_message(&msg); }
defwndproc_counter++; ret = DefMDIChildProcA(hwnd, message, wParam, lParam); defwndproc_counter--;
return ret;}
static LRESULT WINAPI mdi_frame_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ static LONG defwndproc_counter = 0; LRESULT ret; struct recvd_message msg;
/* do not log painting messages */ if (message != WM_PAINT && message != WM_NCPAINT && message != WM_SYNCPAINT && message != WM_ERASEBKGND && message != WM_NCHITTEST && message != WM_GETTEXT && !ignore_message( message )) { msg.hwnd = hwnd; msg.message = message; msg.flags = sent|wparam|lparam; if (defwndproc_counter) msg.flags |= defwinproc; msg.wParam = wParam; msg.lParam = lParam; msg.descr = "mdi frame"; add_message(&msg); }
defwndproc_counter++; ret = DefFrameProcA(hwnd, mdi_client, message, wParam, lParam); defwndproc_counter--;
return ret;}
static BOOL mdi_RegisterWindowClasses(void){ WNDCLASSA cls;
cls.style = 0; cls.lpfnWndProc = mdi_frame_wnd_proc; cls.cbClsExtra = 0; cls.cbWndExtra = 0; cls.hInstance = GetModuleHandleA(0); cls.hIcon = 0; cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); cls.hbrBackground = GetStockObject(WHITE_BRUSH); cls.lpszMenuName = NULL; cls.lpszClassName = "MDI_frame_class"; if (!RegisterClassA(&cls)) return FALSE;
cls.lpfnWndProc = mdi_child_wnd_proc; cls.lpszClassName = "MDI_child_class"; if (!RegisterClassA(&cls)) return FALSE;
if (!GetClassInfoA(0, "MDIClient", &cls)) assert(0); old_mdi_client_proc = cls.lpfnWndProc; cls.hInstance = GetModuleHandleA(0); cls.lpfnWndProc = mdi_client_hook_proc; cls.lpszClassName = "MDI_client_class"; if (!RegisterClassA(&cls)) assert(0);
return TRUE;}
static void test_mdi_messages(void){ MDICREATESTRUCTA mdi_cs; CLIENTCREATESTRUCT client_cs; HWND mdi_frame, mdi_child, mdi_child2, active_child; BOOL zoomed; RECT rc; HMENU hMenu = CreateMenu(); LONG val;
if (!mdi_RegisterWindowClasses()) assert(0);
flush_sequence();
trace("creating MDI frame window\n"); mdi_frame = CreateWindowExA(0, "MDI_frame_class", "MDI frame window", WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_VISIBLE, 100, 100, CW_USEDEFAULT, CW_USEDEFAULT, GetDesktopWindow(), hMenu, GetModuleHandleA(0), NULL); assert(mdi_frame); ok_sequence(WmCreateMDIframeSeq, "Create MDI frame window", FALSE);
ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); ok(GetFocus() == mdi_frame, "wrong focus window %p\n", GetFocus());
trace("creating MDI client window\n"); GetClientRect(mdi_frame, &rc); client_cs.hWindowMenu = 0; client_cs.idFirstChild = MDI_FIRST_CHILD_ID; mdi_client = CreateWindowExA(0, "MDI_client_class", NULL, WS_CHILD | WS_VISIBLE | MDIS_ALLCHILDSTYLES, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, mdi_frame, 0, GetModuleHandleA(0), &client_cs); assert(mdi_client); SetWindowLongA(mdi_client, 0, 0xdeadbeef);
ok_sequence(WmCreateMDIclientSeq, "Create visible MDI client window", FALSE); ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); ok(GetFocus() == mdi_frame, "input focus should be on MDI frame not on %p\n", GetFocus());
active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); ok(!active_child, "wrong active MDI child %p\n", active_child); ok(!zoomed, "wrong zoomed state %d\n", zoomed);
SetFocus(0); flush_sequence();
trace("creating invisible MDI child window\n"); mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", WS_CHILD, 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, mdi_client, 0, GetModuleHandleA(0), NULL); assert(mdi_child);
flush_sequence(); ShowWindow(mdi_child, SW_SHOWNORMAL); ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOWNORMAL) MDI child window", FALSE);
ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n"); ok(IsWindowVisible(mdi_child), "MDI child should be visible\n");
ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); ok(!active_child, "wrong active MDI child %p\n", active_child); ok(!zoomed, "wrong zoomed state %d\n", zoomed);
ShowWindow(mdi_child, SW_HIDE); ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE) MDI child window", FALSE); flush_sequence();
ShowWindow(mdi_child, SW_SHOW); ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW) MDI child window", FALSE);
ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n"); ok(IsWindowVisible(mdi_child), "MDI child should be visible\n");
ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); ok(!active_child, "wrong active MDI child %p\n", active_child); ok(!zoomed, "wrong zoomed state %d\n", zoomed);
DestroyWindow(mdi_child); flush_sequence();
trace("creating visible MDI child window\n"); mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", WS_CHILD | WS_VISIBLE, 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, mdi_client, 0, GetModuleHandleA(0), NULL); assert(mdi_child); ok_sequence(WmCreateMDIchildVisibleSeq, "Create visible MDI child window", FALSE);
ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n"); ok(IsWindowVisible(mdi_child), "MDI child should be visible\n");
ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child); ok(!zoomed, "wrong zoomed state %d\n", zoomed); flush_sequence();
DestroyWindow(mdi_child); ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE);
ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
/* Win2k: MDI client still returns a just destroyed child as active * Win9x: MDI client returns 0 */ active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); ok(active_child == mdi_child || /* win2k */ !active_child, /* win9x */ "wrong active MDI child %p\n", active_child); ok(!zoomed, "wrong zoomed state %d\n", zoomed);
flush_sequence();
trace("creating invisible MDI child window\n"); mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", WS_CHILD, 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, mdi_client, 0, GetModuleHandleA(0), NULL); assert(mdi_child2); ok_sequence(WmCreateMDIchildInvisibleSeq, "Create invisible MDI child window", FALSE);
ok(!(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE), "MDI child should not be visible\n"); ok(!IsWindowVisible(mdi_child2), "MDI child should not be visible\n");
ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
/* Win2k: MDI client still returns a just destroyed child as active * Win9x: MDI client returns mdi_child2 */ active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); ok(active_child == mdi_child || /* win2k */ active_child == mdi_child2, /* win9x */ "wrong active MDI child %p\n", active_child); ok(!zoomed, "wrong zoomed state %d\n", zoomed); flush_sequence();
ShowWindow(mdi_child2, SW_MAXIMIZE); ok_sequence(WmMaximizeMDIchildInvisibleSeq, "ShowWindow(SW_MAXIMIZE):invisible MDI child", FALSE);
ok(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n"); ok(IsWindowVisible(mdi_child2), "MDI child should be visible\n");
active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child); ok(zoomed, "wrong zoomed state %d\n", zoomed); flush_sequence();
ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); ok(GetFocus() == mdi_child2 || /* win2k */ GetFocus() == 0, /* win9x */ "wrong focus window %p\n", GetFocus());
SetFocus(0); flush_sequence();
ShowWindow(mdi_child2, SW_HIDE); ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE);
ShowWindow(mdi_child2, SW_RESTORE); ok_sequence(WmRestoreMDIchildInvisibleSeq, "ShowWindow(SW_RESTORE):invisible MDI child", FALSE); flush_sequence();
ok(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n"); ok(IsWindowVisible(mdi_child2), "MDI child should be visible\n");
active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child); ok(!zoomed, "wrong zoomed state %d\n", zoomed); flush_sequence();
SetFocus(0); flush_sequence();
ShowWindow(mdi_child2, SW_HIDE); ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE);
ShowWindow(mdi_child2, SW_SHOW); ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):MDI child", FALSE);
ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
ShowWindow(mdi_child2, SW_MAXIMIZE); ok_sequence(WmMaximizeMDIchildVisibleSeq, "ShowWindow(SW_MAXIMIZE):MDI child", FALSE);
ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
ShowWindow(mdi_child2, SW_RESTORE); ok_sequence(WmRestoreMDIchildVisibleSeq, "ShowWindow(SW_RESTORE):maximized MDI child", FALSE);
ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
ShowWindow(mdi_child2, SW_MINIMIZE); ok_sequence(WmMinimizeMDIchildVisibleSeq, "ShowWindow(SW_MINIMIZE):MDI child", FALSE);
ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child); ok(!zoomed, "wrong zoomed state %d\n", zoomed); flush_sequence();
ShowWindow(mdi_child2, SW_RESTORE); ok_sequence(WmRestoreMDIchildVisibleSeq_2, "ShowWindow(SW_RESTORE):minimized MDI child", FALSE);
ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); ok(GetFocus() == mdi_child2, "wrong focus window %p\n", GetFocus());
active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child); ok(!zoomed, "wrong zoomed state %d\n", zoomed); flush_sequence();
SetFocus(0); flush_sequence();
ShowWindow(mdi_child2, SW_HIDE); ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):MDI child", FALSE);
ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
DestroyWindow(mdi_child2); ok_sequence(WmDestroyMDIchildInvisibleSeq, "Destroy invisible MDI child window", FALSE);
ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
trace("Testing WM_CHILDACTIVATE\n");
mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_DISABLED, 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, mdi_client, 0, GetModuleHandleA(0), NULL);
mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX, 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, mdi_client, 0, GetModuleHandleA(0), NULL);
active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child); ok(!zoomed, "wrong zoomed state %d\n", zoomed);
flush_sequence(); SendMessageW(mdi_child, WM_CHILDACTIVATE, 0, 0); ok_sequence(WmChildActivateDisabledWindowSeq, "WM_CHILDACTIVATE sent to disabled window", FALSE);
active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child); ok(!zoomed, "wrong zoomed state %d\n", zoomed); flush_sequence();
EnableWindow(mdi_child, TRUE);
active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child); ok(!zoomed, "wrong zoomed state %d\n", zoomed);
flush_sequence(); SendMessageW(mdi_child, WM_CHILDACTIVATE, 0, 0); ok_sequence(WmChildActivateWindowSeq, "WM_CHILDACTIVATE sent to enabled window", FALSE);
active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child); ok(!zoomed, "wrong zoomed state %d\n", zoomed); flush_sequence();
DestroyWindow(mdi_child); DestroyWindow(mdi_child2); flush_sequence();
/* test for maximized MDI children */ trace("creating maximized visible MDI child window 1\n"); mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE, 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, mdi_client, 0, GetModuleHandleA(0), NULL); assert(mdi_child); ok_sequence(WmCreateMDIchildVisibleMaxSeq1, "Create maximized visible 1st MDI child window", TRUE); ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n");
ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); ok(GetFocus() == mdi_child || /* win2k */ GetFocus() == 0, /* win9x */ "wrong focus window %p\n", GetFocus());
active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child); ok(zoomed, "wrong zoomed state %d\n", zoomed); flush_sequence();
trace("creating maximized visible MDI child window 2\n"); mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE, 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, mdi_client, 0, GetModuleHandleA(0), NULL); assert(mdi_child2); ok_sequence(WmCreateMDIchildVisibleMaxSeq2, "Create maximized visible 2nd MDI child 2 window", TRUE); ok(IsZoomed(mdi_child2), "2nd MDI child should be maximized\n"); ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n");
ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); ok(GetFocus() == mdi_child2, "wrong focus window %p\n", GetFocus());
active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child); ok(zoomed, "wrong zoomed state %d\n", zoomed); flush_sequence();
trace("destroying maximized visible MDI child window 2\n"); DestroyWindow(mdi_child2); ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE);
ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n");
ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
/* Win2k: MDI client still returns a just destroyed child as active * Win9x: MDI client returns 0 */ active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); ok(active_child == mdi_child2 || /* win2k */ !active_child, /* win9x */ "wrong active MDI child %p\n", active_child); flush_sequence();
ShowWindow(mdi_child, SW_MAXIMIZE); ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n"); flush_sequence();
ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
trace("re-creating maximized visible MDI child window 2\n"); mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE, 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, mdi_client, 0, GetModuleHandleA(0), NULL); assert(mdi_child2); ok_sequence(WmCreateMDIchildVisibleMaxSeq2, "Create maximized visible 2nd MDI child 2 window", TRUE); ok(IsZoomed(mdi_child2), "2nd MDI child should be maximized\n"); ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized\n");
ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); ok(GetFocus() == mdi_child2, "wrong focus window %p\n", GetFocus());
active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child); ok(zoomed, "wrong zoomed state %d\n", zoomed); flush_sequence();
SendMessageA(mdi_child2, WM_SYSCOMMAND, SC_CLOSE, 0); ok_sequence(WmDestroyMDIchildVisibleMaxSeq2, "WM_SYSCOMMAND/SC_CLOSE on a visible maximized MDI child window", TRUE); ok(!IsWindow(mdi_child2), "MDI child 2 should be destroyed\n");
ok(IsZoomed(mdi_child), "1st MDI child should be maximized\n"); ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child); ok(zoomed, "wrong zoomed state %d\n", zoomed); flush_sequence();
DestroyWindow(mdi_child); ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window", TRUE);
ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
/* Win2k: MDI client still returns a just destroyed child as active * Win9x: MDI client returns 0 */ active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); ok(active_child == mdi_child || /* win2k */ !active_child, /* win9x */ "wrong active MDI child %p\n", active_child); flush_sequence();
trace("creating maximized invisible MDI child window\n"); mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", WS_CHILD | WS_MAXIMIZE | WS_CAPTION | WS_THICKFRAME, 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, mdi_client, 0, GetModuleHandleA(0), NULL); assert(mdi_child2); ok_sequence(WmCreateMDIchildInvisibleMaxSeq4, "Create maximized invisible MDI child window", FALSE); ok(IsZoomed(mdi_child2), "MDI child should be maximized\n"); ok(!(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE), "MDI child should be not visible\n"); ok(!IsWindowVisible(mdi_child2), "MDI child should be not visible\n");
/* Win2k: MDI client still returns a just destroyed child as active * Win9x: MDI client returns 0 */ active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); ok(active_child == mdi_child || /* win2k */ !active_child || active_child == mdi_child2, /* win9x */ "wrong active MDI child %p\n", active_child); flush_sequence();
trace("call ShowWindow(mdi_child, SW_MAXIMIZE)\n"); ShowWindow(mdi_child2, SW_MAXIMIZE); ok_sequence(WmMaximizeMDIchildInvisibleSeq2, "ShowWindow(SW_MAXIMIZE):invisible maximized MDI child", FALSE); ok(IsZoomed(mdi_child2), "MDI child should be maximized\n"); ok(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n"); ok(IsWindowVisible(mdi_child2), "MDI child should be visible\n");
active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); ok(active_child == mdi_child2, "wrong active MDI child %p\n", active_child); ok(zoomed, "wrong zoomed state %d\n", zoomed); flush_sequence();
SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child2, 0); flush_sequence();
/* end of test for maximized MDI children */ SetFocus(0); flush_sequence(); trace("creating maximized visible MDI child window 1(Switch test)\n"); mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE, 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, mdi_client, 0, GetModuleHandleA(0), NULL); assert(mdi_child); ok_sequence(WmCreateMDIchildVisibleMaxSeq1, "Create maximized visible 1st MDI child window(Switch test)", TRUE); ok(IsZoomed(mdi_child), "1st MDI child should be maximized(Switch test)\n");
ok(GetActiveWindow() == mdi_frame, "wrong active window %p(Switch test)\n", GetActiveWindow()); ok(GetFocus() == mdi_child || /* win2k */ GetFocus() == 0, /* win9x */ "wrong focus window %p(Switch test)\n", GetFocus());
active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); ok(active_child == mdi_child, "wrong active MDI child %p(Switch test)\n", active_child); ok(zoomed, "wrong zoomed state %d(Switch test)\n", zoomed); flush_sequence();
trace("creating maximized visible MDI child window 2(Switch test)\n"); mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE, 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, mdi_client, 0, GetModuleHandleA(0), NULL); assert(mdi_child2); ok_sequence(WmCreateMDIchildVisibleMaxSeq2, "Create maximized visible 2nd MDI child window (Switch test)", TRUE);
ok(IsZoomed(mdi_child2), "2nd MDI child should be maximized(Switch test)\n"); ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized(Switch test)\n");
ok(GetActiveWindow() == mdi_frame, "wrong active window %p(Switch test)\n", GetActiveWindow()); ok(GetFocus() == mdi_child2, "wrong focus window %p(Switch test)\n", GetFocus());
active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); ok(active_child == mdi_child2, "wrong active MDI child %p(Switch test)\n", active_child); ok(zoomed, "wrong zoomed state %d(Switch test)\n", zoomed); flush_sequence();
trace("Switch child window.\n"); SendMessageA(mdi_client, WM_MDIACTIVATE, (WPARAM)mdi_child, 0); ok_sequence(WmSwitchChild, "Child did not switch correctly", TRUE); trace("end of test for switch maximized MDI children\n"); flush_sequence();
/* Prepare for switching test of not maximized MDI children */ ShowWindow( mdi_child, SW_NORMAL ); ok(!IsZoomed(mdi_child), "wrong zoomed state for %p(Switch test)\n", mdi_child); ok(!IsZoomed(mdi_child2), "wrong zoomed state for %p(Switch test)\n", mdi_child2); active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0); ok(active_child == mdi_child, "wrong active MDI child %p(Switch test)\n", active_child); flush_sequence();
SendMessageA(mdi_client, WM_MDIACTIVATE, (WPARAM)mdi_child2, 0); ok_sequence(WmSwitchNotMaximizedChild, "Not maximized child did not switch correctly", FALSE); trace("end of test for switch not maximized MDI children\n"); flush_sequence();
SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0); flush_sequence();
SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child2, 0); flush_sequence();
SetFocus(0); flush_sequence(); /* end of tests for switch maximized/not maximized MDI children */
mdi_cs.szClass = "MDI_child_Class"; mdi_cs.szTitle = "MDI child"; mdi_cs.hOwner = GetModuleHandleA(0); mdi_cs.x = 0; mdi_cs.y = 0; mdi_cs.cx = CW_USEDEFAULT; mdi_cs.cy = CW_USEDEFAULT; mdi_cs.style = WS_CHILD | WS_SYSMENU | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE; mdi_cs.lParam = 0; mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs); ok(mdi_child != 0, "MDI child creation failed\n"); ok_sequence(WmCreateMDIchildVisibleMaxSeq3, "WM_MDICREATE for maximized visible MDI child window", TRUE);
ok(GetMenuItemID(hMenu, GetMenuItemCount(hMenu) - 1) == SC_CLOSE, "SC_CLOSE menu item not found\n");
active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child);
ok(IsZoomed(mdi_child), "MDI child should be maximized\n"); ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow()); ok(GetFocus() == mdi_child, "wrong focus window %p\n", GetFocus());
active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); ok(active_child == mdi_child, "wrong active MDI child %p\n", active_child); ok(zoomed, "wrong zoomed state %d\n", zoomed); flush_sequence();
SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0); ok_sequence(WmDestroyMDIchildVisibleMaxSeq1, "Destroy visible maximized MDI child window", TRUE);
ok(!IsWindow(mdi_child), "MDI child should be destroyed\n"); active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); ok(!active_child, "wrong active MDI child %p\n", active_child);
SetFocus(0); flush_sequence();
val = GetWindowLongA(mdi_client, 0); ok(val == 0xdeadbeef || broken(val == 0) /* >= Win Vista */, "Expected 0xdeadbeef, got 0x%x\n", val); DestroyWindow(mdi_client); ok_sequence(WmDestroyMDIclientSeq, "Destroy MDI client window", FALSE);
/* test maximization of MDI child with invisible parent */ client_cs.hWindowMenu = 0; mdi_client = CreateWindowA("MDI_client_class", NULL, WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL | WS_VISIBLE, 0, 0, 660, 430, mdi_frame, 0, GetModuleHandleA(0), &client_cs); ok_sequence(WmCreateMDIclientSeq, "Create MDI client window", FALSE);
ShowWindow(mdi_client, SW_HIDE); ok_sequence(WmHideMDIclientSeq, "Hide MDI client window", FALSE);
mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL, 0, 0, 650, 440, mdi_client, 0, GetModuleHandleA(0), NULL); ok_sequence(WmCreateMDIchildInvisibleParentSeq, "Create MDI child window with invisible parent", FALSE);
SendMessageA(mdi_client, WM_MDIMAXIMIZE, (WPARAM) mdi_child, 0); ok_sequence(WmMaximizeMDIchildInvisibleParentSeq, "Maximize MDI child window with invisible parent", TRUE); zoomed = IsZoomed(mdi_child); ok(zoomed, "wrong zoomed state %d\n", zoomed);
ShowWindow(mdi_client, SW_SHOW); ok_sequence(WmShowMDIclientSeq, "Show MDI client window", FALSE);
DestroyWindow(mdi_child); ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible maximized MDI child window", TRUE);
/* end of test for maximization of MDI child with invisible parent */
DestroyWindow(mdi_client); ok_sequence(WmDestroyMDIclientSeq, "Destroy MDI client window", FALSE);
DestroyWindow(mdi_frame); ok_sequence(WmDestroyMDIframeSeq, "Destroy MDI frame window", FALSE);}/************************* End of MDI test **********************************/
static void test_WM_SETREDRAW(HWND hwnd){ DWORD style = GetWindowLongA(hwnd, GWL_STYLE);
flush_events(); flush_sequence();
SendMessageA(hwnd, WM_SETREDRAW, FALSE, 0); ok_sequence(WmSetRedrawFalseSeq, "SetRedraw:FALSE", FALSE);
ok(!(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should NOT be set\n"); ok(!IsWindowVisible(hwnd), "IsWindowVisible() should return FALSE\n");
flush_sequence(); SendMessageA(hwnd, WM_SETREDRAW, TRUE, 0); ok_sequence(WmSetRedrawTrueSeq, "SetRedraw:TRUE", FALSE);
ok(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); ok(IsWindowVisible(hwnd), "IsWindowVisible() should return TRUE\n");
/* restore original WS_VISIBLE state */ SetWindowLongA(hwnd, GWL_STYLE, style);
flush_events(); flush_sequence();}
static INT_PTR CALLBACK TestModalDlgProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ struct recvd_message msg;
if (ignore_message( message )) return 0;
switch (message) { /* ignore */ case WM_MOUSEMOVE: case WM_NCMOUSEMOVE: case WM_NCMOUSELEAVE: case WM_SETCURSOR: return 0; case WM_NCHITTEST: return HTCLIENT; }
msg.hwnd = hwnd; msg.message = message; msg.flags = sent|wparam|lparam; msg.wParam = wParam; msg.lParam = lParam; msg.descr = "dialog"; add_message(&msg);
if (message == WM_INITDIALOG) SetTimer( hwnd, 1, 100, NULL ); if (message == WM_TIMER) EndDialog( hwnd, 0 ); return 0;}
static INT_PTR CALLBACK TestModalDlgProc2(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ struct recvd_message msg;
if (ignore_message( message )) return 0;
switch (message) { /* ignore */ case WM_MOUSEMOVE: case WM_NCMOUSEMOVE: case WM_NCMOUSELEAVE: case WM_SETCURSOR: return 0; case WM_NCHITTEST: return HTCLIENT; }
msg.hwnd = hwnd; msg.message = message; msg.flags = sent|wparam|lparam; msg.wParam = wParam; msg.lParam = lParam; msg.descr = "dialog"; add_message(&msg);
if (message == WM_INITDIALOG) EndDialog( hwnd, 0 ); return 0;}
static void test_hv_scroll_1(HWND hwnd, INT ctl, DWORD clear, DWORD set, INT min, INT max){ DWORD style, exstyle; INT xmin, xmax; BOOL ret;
exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE); style = GetWindowLongA(hwnd, GWL_STYLE); /* do not be confused by WS_DLGFRAME set */ if ((style & WS_CAPTION) == WS_CAPTION) style &= ~WS_CAPTION;
if (clear) ok(style & clear, "style %08x should be set\n", clear); if (set) ok(!(style & set), "style %08x should not be set\n", set);
ret = SetScrollRange(hwnd, ctl, min, max, FALSE); ok( ret, "SetScrollRange(%d) error %d\n", ctl, GetLastError()); if ((style & (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME)) || (exstyle & WS_EX_DLGMODALFRAME)) ok_sequence(WmSetScrollRangeHV_NC_Seq, "SetScrollRange(SB_HORZ/SB_VERT) NC", FALSE); else ok_sequence(WmSetScrollRangeHVSeq, "SetScrollRange(SB_HORZ/SB_VERT)", FALSE);
style = GetWindowLongA(hwnd, GWL_STYLE); if (set) ok(style & set, "style %08x should be set\n", set); if (clear) ok(!(style & clear), "style %08x should not be set\n", clear);
/* a subsequent call should do nothing */ ret = SetScrollRange(hwnd, ctl, min, max, FALSE); ok( ret, "SetScrollRange(%d) error %d\n", ctl, GetLastError()); ok_sequence(WmEmptySeq, "SetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE);
xmin = 0xdeadbeef; xmax = 0xdeadbeef; ret = GetScrollRange(hwnd, ctl, &xmin, &xmax); ok( ret, "GetScrollRange(%d) error %d\n", ctl, GetLastError()); ok_sequence(WmEmptySeq, "GetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE); ok(xmin == min, "unexpected min scroll value %d\n", xmin); ok(xmax == max, "unexpected max scroll value %d\n", xmax);}
static void test_hv_scroll_2(HWND hwnd, INT ctl, DWORD clear, DWORD set, INT min, INT max){ DWORD style, exstyle; SCROLLINFO si; BOOL ret;
exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE); style = GetWindowLongA(hwnd, GWL_STYLE); /* do not be confused by WS_DLGFRAME set */ if ((style & WS_CAPTION) == WS_CAPTION) style &= ~WS_CAPTION;
if (clear) ok(style & clear, "style %08x should be set\n", clear); if (set) ok(!(style & set), "style %08x should not be set\n", set);
si.cbSize = sizeof(si); si.fMask = SIF_RANGE; si.nMin = min; si.nMax = max; SetScrollInfo(hwnd, ctl, &si, TRUE); if ((style & (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME)) || (exstyle & WS_EX_DLGMODALFRAME)) ok_sequence(WmSetScrollRangeHV_NC_Seq, "SetScrollInfo(SB_HORZ/SB_VERT) NC", FALSE); else ok_sequence(WmSetScrollRangeHVSeq, "SetScrollInfo(SB_HORZ/SB_VERT)", FALSE);
style = GetWindowLongA(hwnd, GWL_STYLE); if (set) ok(style & set, "style %08x should be set\n", set); if (clear) ok(!(style & clear), "style %08x should not be set\n", clear);
/* a subsequent call should do nothing */ SetScrollInfo(hwnd, ctl, &si, TRUE); if (style & WS_HSCROLL) ok_sequence(WmSetScrollRangeHSeq_empty, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE); else if (style & WS_VSCROLL) ok_sequence(WmSetScrollRangeVSeq_empty, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE); else ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE);
si.fMask = SIF_PAGE; si.nPage = 5; SetScrollInfo(hwnd, ctl, &si, FALSE); ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE);
si.fMask = SIF_POS; si.nPos = max - 1; SetScrollInfo(hwnd, ctl, &si, FALSE); ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT) empty sequence", FALSE);
si.fMask = SIF_RANGE; si.nMin = 0xdeadbeef; si.nMax = 0xdeadbeef; ret = GetScrollInfo(hwnd, ctl, &si); ok( ret, "GetScrollInfo error %d\n", GetLastError()); ok_sequence(WmEmptySeq, "GetScrollRange(SB_HORZ/SB_VERT) empty sequence", FALSE); ok(si.nMin == min, "unexpected min scroll value %d\n", si.nMin); ok(si.nMax == max, "unexpected max scroll value %d\n", si.nMax);}
/* Win9x sends WM_USER+xxx while and NT versions send SBM_xxx messages */static void test_scroll_messages(HWND hwnd){ SCROLLINFO si; INT min, max; BOOL ret;
flush_events(); flush_sequence();
min = 0xdeadbeef; max = 0xdeadbeef; ret = GetScrollRange(hwnd, SB_CTL, &min, &max); ok( ret, "GetScrollRange error %d\n", GetLastError()); if (sequence->message != WmGetScrollRangeSeq[0].message) trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message); /* values of min and max are undefined */ flush_sequence();
ret = SetScrollRange(hwnd, SB_CTL, 10, 150, FALSE); ok( ret, "SetScrollRange error %d\n", GetLastError()); if (sequence->message != WmSetScrollRangeSeq[0].message) trace("SetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message); flush_sequence();
min = 0xdeadbeef; max = 0xdeadbeef; ret = GetScrollRange(hwnd, SB_CTL, &min, &max); ok( ret, "GetScrollRange error %d\n", GetLastError()); if (sequence->message != WmGetScrollRangeSeq[0].message) trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message); /* values of min and max are undefined */ flush_sequence();
si.cbSize = sizeof(si); si.fMask = SIF_RANGE; si.nMin = 20; si.nMax = 160; SetScrollInfo(hwnd, SB_CTL, &si, FALSE); if (sequence->message != WmSetScrollRangeSeq[0].message) trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message); flush_sequence();
si.fMask = SIF_PAGE; si.nPage = 10; SetScrollInfo(hwnd, SB_CTL, &si, FALSE); if (sequence->message != WmSetScrollRangeSeq[0].message) trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message); flush_sequence();
si.fMask = SIF_POS; si.nPos = 20; SetScrollInfo(hwnd, SB_CTL, &si, FALSE); if (sequence->message != WmSetScrollRangeSeq[0].message) trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message); flush_sequence();
si.fMask = SIF_RANGE; si.nMin = 0xdeadbeef; si.nMax = 0xdeadbeef; ret = GetScrollInfo(hwnd, SB_CTL, &si); ok( ret, "GetScrollInfo error %d\n", GetLastError()); if (sequence->message != WmGetScrollInfoSeq[0].message) trace("GetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message); /* values of min and max are undefined */ flush_sequence();
/* set WS_HSCROLL */ test_hv_scroll_1(hwnd, SB_HORZ, 0, WS_HSCROLL, 10, 150); /* clear WS_HSCROLL */ test_hv_scroll_1(hwnd, SB_HORZ, WS_HSCROLL, 0, 0, 0);
/* set WS_HSCROLL */ test_hv_scroll_2(hwnd, SB_HORZ, 0, WS_HSCROLL, 10, 150); /* clear WS_HSCROLL */ test_hv_scroll_2(hwnd, SB_HORZ, WS_HSCROLL, 0, 0, 0);
/* set WS_VSCROLL */ test_hv_scroll_1(hwnd, SB_VERT, 0, WS_VSCROLL, 10, 150); /* clear WS_VSCROLL */ test_hv_scroll_1(hwnd, SB_VERT, WS_VSCROLL, 0, 0, 0);
/* set WS_VSCROLL */ test_hv_scroll_2(hwnd, SB_VERT, 0, WS_VSCROLL, 10, 150); /* clear WS_VSCROLL */ test_hv_scroll_2(hwnd, SB_VERT, WS_VSCROLL, 0, 0, 0);}
static void test_showwindow(void){ HWND hwnd, hchild; RECT rc;
hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW, 100, 100, 200, 200, 0, 0, 0, NULL); ok (hwnd != 0, "Failed to create overlapped window\n"); hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 0, 0, 10, 10, hwnd, 0, 0, NULL); ok (hchild != 0, "Failed to create child\n"); flush_sequence();
/* ShowWindow( SW_SHOWNA) for invisible top level window */ trace("calling ShowWindow( SW_SHOWNA) for invisible top level window\n"); ok( ShowWindow(hwnd, SW_SHOWNA) == FALSE, "ShowWindow: window was visible\n" ); ok_sequence(WmSHOWNATopInvisible, "ShowWindow(SW_SHOWNA) on invisible top level window", FALSE);
/* ShowWindow( SW_SHOWNA) for now visible top level window */ trace("calling ShowWindow( SW_SHOWNA) for now visible top level window\n"); ok( ShowWindow(hwnd, SW_SHOWNA) != FALSE, "ShowWindow: window was invisible\n" ); ok_sequence(WmSHOWNATopVisible, "ShowWindow(SW_SHOWNA) on visible top level window", FALSE); /* back to invisible */ ShowWindow(hchild, SW_HIDE); ShowWindow(hwnd, SW_HIDE); flush_sequence(); /* ShowWindow(SW_SHOWNA) with child and parent invisible */ trace("calling ShowWindow( SW_SHOWNA) for invisible child with invisible parent\n"); ok( ShowWindow(hchild, SW_SHOWNA) == FALSE, "ShowWindow: window was visible\n" ); ok_sequence(WmSHOWNAChildInvisParInvis, "ShowWindow(SW_SHOWNA) invisible child and parent", FALSE); /* ShowWindow(SW_SHOWNA) with child visible and parent invisible */ ok( ShowWindow(hchild, SW_SHOW) != FALSE, "ShowWindow: window was invisible\n" ); flush_sequence(); trace("calling ShowWindow( SW_SHOWNA) for the visible child and invisible parent\n"); ok( ShowWindow(hchild, SW_SHOWNA) != FALSE, "ShowWindow: window was invisible\n" ); ok_sequence(WmSHOWNAChildVisParInvis, "ShowWindow(SW_SHOWNA) visible child and invisible parent", FALSE); /* ShowWindow(SW_SHOWNA) with child visible and parent visible */ ShowWindow( hwnd, SW_SHOW); flush_sequence(); trace("calling ShowWindow( SW_SHOWNA) for the visible child and parent\n"); ok( ShowWindow(hchild, SW_SHOWNA) != FALSE, "ShowWindow: window was invisible\n" ); ok_sequence(WmSHOWNAChildVisParVis, "ShowWindow(SW_SHOWNA) for the visible child and parent", FALSE);
/* ShowWindow(SW_SHOWNA) with child invisible and parent visible */ ShowWindow( hchild, SW_HIDE); flush_sequence(); trace("calling ShowWindow( SW_SHOWNA) for the invisible child and visible parent\n"); ok( ShowWindow(hchild, SW_SHOWNA) == FALSE, "ShowWindow: window was visible\n" ); ok_sequence(WmSHOWNAChildInvisParVis, "ShowWindow(SW_SHOWNA) for the invisible child and visible parent", FALSE);
SetCapture(hchild); ok(GetCapture() == hchild, "wrong capture window %p\n", GetCapture()); DestroyWindow(hchild); ok(!GetCapture(), "wrong capture window %p\n", GetCapture());
DestroyWindow(hwnd); flush_sequence();
/* Popup windows */ /* Test 1: * 1. Create invisible maximized popup window. * 2. Move and resize it. * 3. Show it maximized. */ trace("calling CreateWindowExA( WS_MAXIMIZE ) for invisible maximized popup window\n"); hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_MAXIMIZE, 100, 100, 200, 200, 0, 0, 0, NULL); ok (hwnd != 0, "Failed to create popup window\n"); ok(IsZoomed(hwnd), "window should be maximized\n"); ok_sequence(WmCreateInvisibleMaxPopupSeq, "CreateWindow(WS_MAXIMIZED):popup", FALSE);
GetWindowRect(hwnd, &rc); ok( rc.right-rc.left == GetSystemMetrics(SM_CXSCREEN) && rc.bottom-rc.top == GetSystemMetrics(SM_CYSCREEN), "Invalid maximized size before ShowWindow %s\n", wine_dbgstr_rect( &rc )); /* Reset window's size & position */ SetWindowPos(hwnd, 0, 10, 10, 200, 200, SWP_NOZORDER | SWP_NOACTIVATE); ok(IsZoomed(hwnd), "window should be maximized\n"); flush_sequence();
trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for invisible maximized popup window\n"); ShowWindow(hwnd, SW_SHOWMAXIMIZED); ok(IsZoomed(hwnd), "window should be maximized\n"); ok_sequence(WmShowMaxPopupResizedSeq, "ShowWindow(SW_SHOWMAXIMIZED):invisible maximized and resized popup", FALSE);
GetWindowRect(hwnd, &rc); ok( rc.right-rc.left == GetSystemMetrics(SM_CXSCREEN) && rc.bottom-rc.top == GetSystemMetrics(SM_CYSCREEN), "Invalid maximized size after ShowWindow %s\n", wine_dbgstr_rect( &rc )); DestroyWindow(hwnd); flush_sequence();
/* Test 2: * 1. Create invisible maximized popup window. * 2. Show it maximized. */ trace("calling CreateWindowExA( WS_MAXIMIZE ) for invisible maximized popup window\n"); hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_MAXIMIZE, 100, 100, 200, 200, 0, 0, 0, NULL); ok (hwnd != 0, "Failed to create popup window\n"); ok(IsZoomed(hwnd), "window should be maximized\n"); ok_sequence(WmCreateInvisibleMaxPopupSeq, "CreateWindow(WS_MAXIMIZED):popup", FALSE);
trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for invisible maximized popup window\n"); ShowWindow(hwnd, SW_SHOWMAXIMIZED); ok(IsZoomed(hwnd), "window should be maximized\n"); ok_sequence(WmShowMaxPopupSeq, "ShowWindow(SW_SHOWMAXIMIZED):invisible maximized popup", FALSE); DestroyWindow(hwnd); flush_sequence();
/* Test 3: * 1. Create visible maximized popup window. */ trace("calling CreateWindowExA( WS_MAXIMIZE ) for maximized popup window\n"); hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_MAXIMIZE | WS_VISIBLE, 100, 100, 200, 200, 0, 0, 0, NULL); ok (hwnd != 0, "Failed to create popup window\n"); ok(IsZoomed(hwnd), "window should be maximized\n"); ok_sequence(WmCreateMaxPopupSeq, "CreateWindow(WS_MAXIMIZED):popup", FALSE); DestroyWindow(hwnd); flush_sequence();
/* Test 4: * 1. Create visible popup window. * 2. Maximize it. */ trace("calling CreateWindowExA( WS_VISIBLE ) for popup window\n"); hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_VISIBLE, 100, 100, 200, 200, 0, 0, 0, NULL); ok (hwnd != 0, "Failed to create popup window\n"); ok(!IsZoomed(hwnd), "window should NOT be maximized\n"); ok_sequence(WmCreatePopupSeq, "CreateWindow(WS_VISIBLE):popup", FALSE);
trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for visible popup window\n"); ShowWindow(hwnd, SW_SHOWMAXIMIZED); ok(IsZoomed(hwnd), "window should be maximized\n"); ok_sequence(WmShowVisMaxPopupSeq, "ShowWindow(SW_SHOWMAXIMIZED):popup", FALSE); DestroyWindow(hwnd); flush_sequence();}
static void test_recursive_activation(void){ static const struct message seq[] = { { HCBT_ACTIVATE, hook }, { WM_NCACTIVATE, sent|wparam, TRUE }, { WM_ACTIVATE, sent|wparam, WA_ACTIVE }, { HCBT_ACTIVATE, hook }, { WM_NCACTIVATE, sent|wparam, FALSE }, { WM_ACTIVATE, sent|wparam, WA_INACTIVE }, { WM_SETFOCUS, sent|optional }, { 0 } }; HWND hwnd, recursive;
hwnd = CreateWindowExA(0, "SimpleWindowClass", NULL, WS_OVERLAPPED|WS_VISIBLE, 100, 100, 200, 200, 0, 0, 0, NULL); ok(hwnd != 0, "Failed to create simple window\n");
recursive = CreateWindowExA(0, "RecursiveActivationClass", NULL, WS_OVERLAPPED|WS_VISIBLE, 10, 10, 50, 50, hwnd, 0, 0, NULL); ok(recursive != 0, "Failed to create recursive activation window\n"); SetActiveWindow(hwnd);
flush_sequence(); SetActiveWindow(recursive); ok_sequence(seq, "Recursive Activation", FALSE);
DestroyWindow(recursive); DestroyWindow(hwnd); flush_sequence();}
static void test_sys_menu(void){ HWND hwnd; HMENU hmenu; UINT state;
hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW, 100, 100, 200, 200, 0, 0, 0, NULL); ok (hwnd != 0, "Failed to create overlapped window\n");
flush_sequence();
/* test existing window without CS_NOCLOSE style */ hmenu = GetSystemMenu(hwnd, FALSE); ok(hmenu != 0, "GetSystemMenu error %d\n", GetLastError());
state = GetMenuState(hmenu, SC_CLOSE, MF_BYCOMMAND); ok(state != 0xffffffff, "wrong SC_CLOSE state %x\n", state); ok(!(state & (MF_DISABLED | MF_GRAYED)), "wrong SC_CLOSE state %x\n", state);
EnableMenuItem(hmenu, SC_CLOSE, MF_BYCOMMAND | MF_GRAYED); ok_sequence(WmEmptySeq, "WmEnableMenuItem", FALSE);
state = GetMenuState(hmenu, SC_CLOSE, MF_BYCOMMAND); ok(state != 0xffffffff, "wrong SC_CLOSE state %x\n", state); ok((state & (MF_DISABLED | MF_GRAYED)) == MF_GRAYED, "wrong SC_CLOSE state %x\n", state);
EnableMenuItem(hmenu, SC_CLOSE, 0); ok_sequence(WmEmptySeq, "WmEnableMenuItem", FALSE);
state = GetMenuState(hmenu, SC_CLOSE, MF_BYCOMMAND); ok(state != 0xffffffff, "wrong SC_CLOSE state %x\n", state); ok(!(state & (MF_DISABLED | MF_GRAYED)), "wrong SC_CLOSE state %x\n", state);
/* test whether removing WS_SYSMENU destroys a system menu */ SetWindowLongW(hwnd, GWL_STYLE, WS_POPUP); SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_FRAMECHANGED); flush_sequence(); hmenu = GetSystemMenu(hwnd, FALSE); ok(hmenu != 0, "GetSystemMenu error %d\n", GetLastError());
DestroyWindow(hwnd);
/* test new window with CS_NOCLOSE style */ hwnd = CreateWindowExA(0, "NoCloseWindowClass", NULL, WS_OVERLAPPEDWINDOW, 100, 100, 200, 200, 0, 0, 0, NULL); ok (hwnd != 0, "Failed to create overlapped window\n");
hmenu = GetSystemMenu(hwnd, FALSE); ok(hmenu != 0, "GetSystemMenu error %d\n", GetLastError());
state = GetMenuState(hmenu, SC_CLOSE, MF_BYCOMMAND); ok(state == 0xffffffff, "wrong SC_CLOSE state %x\n", state);
DestroyWindow(hwnd);
/* test new window without WS_SYSMENU style */ hwnd = CreateWindowExA(0, "NoCloseWindowClass", NULL, WS_OVERLAPPEDWINDOW & ~WS_SYSMENU, 100, 100, 200, 200, 0, 0, 0, NULL); ok(hwnd != 0, "Failed to create overlapped window\n");
hmenu = GetSystemMenu(hwnd, FALSE); ok(!hmenu, "GetSystemMenu error %d\n", GetLastError());
DestroyWindow(hwnd);}
/* For shown WS_OVERLAPPEDWINDOW */static const struct message WmSetIcon_1[] = { { WM_SETICON, sent }, { 0x00AE, sent|defwinproc|optional }, /* XP */ { WM_GETTEXT, sent|defwinproc|optional }, { WM_GETTEXT, sent|defwinproc|optional }, /* XP sends a duplicate */ { 0 }};
/* For WS_POPUP and hidden WS_OVERLAPPEDWINDOW */static const struct message WmSetIcon_2[] = { { WM_SETICON, sent }, { 0 }};
/* Sending undocumented 0x3B message with wparam = 0x8000000b */static const struct message WmInitEndSession[] = { { 0x003B, sent }, { WM_QUERYENDSESSION, sent|defwinproc|wparam|lparam, 0, ENDSESSION_LOGOFF }, { 0 }};
/* Sending undocumented 0x3B message with wparam = 0x0000000b */static const struct message WmInitEndSession_2[] = { { 0x003B, sent }, { WM_QUERYENDSESSION, sent|defwinproc|wparam|lparam, 0, 0 }, { 0 }};
/* Sending undocumented 0x3B message with wparam = 0x80000008 */static const struct message WmInitEndSession_3[] = { { 0x003B, sent }, { WM_ENDSESSION, sent|defwinproc|wparam|lparam, 0, ENDSESSION_LOGOFF }, { 0 }};
/* Sending undocumented 0x3B message with wparam = 0x00000008 */static const struct message WmInitEndSession_4[] = { { 0x003B, sent }, { WM_ENDSESSION, sent|defwinproc|wparam|lparam, 0, 0 }, { 0 }};
/* Sending undocumented 0x3B message with wparam = 0x80000001 */static const struct message WmInitEndSession_5[] = { { 0x003B, sent }, { WM_ENDSESSION, sent|defwinproc/*|wparam*/|lparam, 1, ENDSESSION_LOGOFF }, { 0 }};
static const struct message WmOptionalPaint[] = { { WM_PAINT, sent|optional }, { WM_NCPAINT, sent|beginpaint|optional }, { WM_GETTEXT, sent|beginpaint|defwinproc|optional }, { WM_ERASEBKGND, sent|beginpaint|optional }, { 0 }};
static const struct message WmZOrder[] = { { WM_WINDOWPOSCHANGING, sent|wparam, 0, 0 }, { WM_GETMINMAXINFO, sent|defwinproc|wparam, 0, 0 }, { HCBT_ACTIVATE, hook }, { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam, 3, 0 }, { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOREDRAW|SWP_NOMOVE|SWP_NOSIZE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE, 0 }, { WM_GETTEXT, sent|optional }, { WM_NCCALCSIZE, sent|wparam|optional, 1 }, { WM_ACTIVATEAPP, sent|wparam, 1, 0 }, { WM_NCACTIVATE, sent|lparam, 1, 0 }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ACTIVATE, sent|wparam|lparam, 1, 0 }, { HCBT_SETFOCUS, hook }, { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { WM_GETTEXT, sent|optional }, { WM_NCCALCSIZE, sent|optional }, { 0 }};
static void CALLBACK apc_test_proc(ULONG_PTR param){ /* nothing */}
static void test_MsgWaitForMultipleObjects(HWND hwnd){ DWORD ret; MSG msg;
ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE); ok(ret == WAIT_TIMEOUT, "MsgWaitForMultipleObjects returned %x\n", ret);
PostMessageA(hwnd, WM_USER, 0, 0);
ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE); ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjects returned %x\n", ret);
ok(PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n"); ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message);
ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE); ok(ret == WAIT_TIMEOUT, "MsgWaitForMultipleObjects returned %x\n", ret);
PostMessageA(hwnd, WM_USER, 0, 0);
ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE); ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjects returned %x\n", ret);
ok(PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ), "PeekMessage should succeed\n"); ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message);
/* shows QS_POSTMESSAGE flag is cleared in the PeekMessage call */ ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE); ok(ret == WAIT_TIMEOUT, "MsgWaitForMultipleObjects returned %x\n", ret);
PostMessageA(hwnd, WM_USER, 0, 0);
/* new incoming message causes it to become signaled again */ ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE); ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjects returned %x\n", ret);
ok(PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n"); ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message); ok(PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n"); ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message);
/* MWMO_INPUTAVAILABLE should succeed even if the message was already seen */ PostMessageA( hwnd, WM_USER, 0, 0 ); ok(PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ), "PeekMessage should succeed\n"); ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message);
ret = MsgWaitForMultipleObjectsEx( 0, NULL, 0, QS_POSTMESSAGE, MWMO_INPUTAVAILABLE ); ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjectsEx returned %x\n", ret);
ok(PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n"); ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message);
/* without MWMO_ALERTABLE the result is never WAIT_IO_COMPLETION */ ret = QueueUserAPC( apc_test_proc, GetCurrentThread(), 0 ); ok(ret, "QueueUserAPC failed %u\n", GetLastError());
ret = MsgWaitForMultipleObjectsEx( 0, NULL, 0, QS_POSTMESSAGE, 0 ); ok(ret == WAIT_TIMEOUT, "MsgWaitForMultipleObjectsEx returned %x\n", ret);
/* but even with MWMO_ALERTABLE window events are preferred */ PostMessageA( hwnd, WM_USER, 0, 0 );
ret = MsgWaitForMultipleObjectsEx( 0, NULL, 0, QS_POSTMESSAGE, MWMO_ALERTABLE ); ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjectsEx returned %x\n", ret);
ok(PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n"); ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message);
/* the APC call is still queued */ ret = MsgWaitForMultipleObjectsEx( 0, NULL, 0, QS_POSTMESSAGE, MWMO_ALERTABLE ); ok(ret == WAIT_IO_COMPLETION, "MsgWaitForMultipleObjectsEx returned %x\n", ret);}
static void test_WM_DEVICECHANGE(HWND hwnd){ DWORD ret; MSG msg; int i; static const WPARAM wparams[] = {0, DBT_DEVNODES_CHANGED, DBT_QUERYCHANGECONFIG, DBT_CONFIGCHANGED, DBT_CONFIGCHANGECANCELED, DBT_NO_DISK_SPACE, DBT_LOW_DISK_SPACE, DBT_CONFIGMGPRIVATE, /* 0x7fff */ DBT_DEVICEARRIVAL, /* 0x8000 */ DBT_DEVICEQUERYREMOVE, DBT_DEVICEQUERYREMOVEFAILED, DBT_DEVICEREMOVEPENDING, DBT_DEVICEREMOVECOMPLETE, DBT_DEVICETYPESPECIFIC, DBT_CUSTOMEVENT};
for (i = 0; i < ARRAY_SIZE(wparams); i++) { SetLastError(0xdeadbeef); ret = PostMessageA(hwnd, WM_DEVICECHANGE, wparams[i], 0); if (wparams[i] & 0x8000) { ok(ret == FALSE, "PostMessage should returned %d\n", ret); ok(GetLastError() == ERROR_MESSAGE_SYNC_ONLY, "PostMessage error %08x\n", GetLastError()); } else { ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE); ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjects returned %x\n", ret); memset(&msg, 0, sizeof(msg)); ok(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "PeekMessage should succeed\n"); ok(msg.message == WM_DEVICECHANGE, "got %04x instead of WM_DEVICECHANGE\n", msg.message); } }}
static DWORD CALLBACK show_window_thread(LPVOID arg){ HWND hwnd = arg;
/* function will not return if ShowWindow(SW_HIDE) calls SendMessage() */ ok(ShowWindow(hwnd, SW_HIDE) == FALSE, "ShowWindow(SW_HIDE) expected FALSE\n");
return 0;}
/* Helper function to easier test SetWindowPos messages */#define test_msg_setpos( expected_list, flags, todo ) \ test_msg_setpos_( (expected_list), (flags), (todo), __FILE__, __LINE__)static void test_msg_setpos_(const struct message *expected_list, UINT flags, BOOL todo, const char *file, int line){ HWND hwnd;
flush_events(); flush_sequence(); hwnd = CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP, 10, 10, 100, 100, NULL, 0, 0, NULL ); ok (hwnd != 0, "Failed to create popup window\n"); SetWindowPos(hwnd, NULL, 0, 0, 100, 100, flags); ok_sequence_(expected_list, "SetWindowPos:show_popup_first_show_window", todo, file, line); DestroyWindow(hwnd);}
/* test if we receive the right sequence of messages */static void test_messages(void){ DWORD tid; HANDLE hthread; HWND hwnd, hparent, hchild; HWND hchild2, hbutton; HMENU hmenu; MSG msg; LRESULT res; POINT pos; BOOL ret;
flush_sequence();
hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW, 100, 100, 200, 200, 0, 0, 0, NULL); ok (hwnd != 0, "Failed to create overlapped window\n"); ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped", FALSE);
/* test ShowWindow(SW_HIDE) on a newly created invisible window */ ok( ShowWindow(hwnd, SW_HIDE) == FALSE, "ShowWindow: window was visible\n" ); ok_sequence(WmEmptySeq, "ShowWindow(SW_HIDE):overlapped, invisible", FALSE);
/* test WM_SETREDRAW on a not visible top level window */ test_WM_SETREDRAW(hwnd);
SetWindowPos(hwnd, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE); flush_events(); ok_sequence(WmSWP_ShowOverlappedSeq, "SetWindowPos:SWP_SHOWWINDOW:overlapped", FALSE); ok(IsWindowVisible(hwnd), "window should be visible at this point\n");
ok(GetActiveWindow() == hwnd, "window should be active\n"); ok(GetFocus() == hwnd, "window should have input focus\n"); ShowWindow(hwnd, SW_HIDE); flush_events(); ok_sequence(WmHideOverlappedSeq, "ShowWindow(SW_HIDE):overlapped", FALSE);
/* test ShowWindow(SW_HIDE) on a hidden window - single threaded */ ok(ShowWindow(hwnd, SW_HIDE) == FALSE, "ShowWindow(SW_HIDE) expected FALSE\n"); flush_events(); ok_sequence(WmEmptySeq, "ShowWindow(SW_HIDE):overlapped", FALSE);
/* test ShowWindow(SW_HIDE) on a hidden window - multi-threaded */ hthread = CreateThread(NULL, 0, show_window_thread, hwnd, 0, &tid); ok(hthread != NULL, "CreateThread failed, error %d\n", GetLastError()); ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); CloseHandle(hthread); flush_events(); ok_sequence(WmEmptySeq, "ShowWindow(SW_HIDE):overlapped", FALSE);
ShowWindow(hwnd, SW_SHOW); flush_events(); ok_sequence(WmShowOverlappedSeq, "ShowWindow(SW_SHOW):overlapped", TRUE);
ShowWindow(hwnd, SW_HIDE); flush_events(); ok_sequence(WmHideOverlappedSeq, "ShowWindow(SW_HIDE):overlapped", FALSE);
ShowWindow(hwnd, SW_SHOWMAXIMIZED); flush_events(); ok_sequence(WmShowMaxOverlappedSeq, "ShowWindow(SW_SHOWMAXIMIZED):overlapped", TRUE); flush_sequence();
if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_MAXIMIZE) { ShowWindow(hwnd, SW_RESTORE); flush_events(); ok_sequence(WmShowRestoreMaxOverlappedSeq, "ShowWindow(SW_RESTORE):overlapped", TRUE); flush_sequence(); }
ShowWindow(hwnd, SW_MINIMIZE); flush_events(); ok_sequence(WmShowMinOverlappedSeq, "ShowWindow(SW_SHOWMINIMIZED):overlapped", FALSE); flush_sequence();
if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_MINIMIZE) { ShowWindow(hwnd, SW_RESTORE); flush_events(); ok_sequence(WmShowRestoreMinOverlappedSeq, "ShowWindow(SW_RESTORE):overlapped", TRUE); flush_sequence(); }
ShowWindow(hwnd, SW_SHOW); flush_events(); ok_sequence(WmOptionalPaint, "ShowWindow(SW_SHOW):overlapped already visible", FALSE);
SetWindowPos(hwnd, 0,0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE); ok_sequence(WmSWP_HideOverlappedSeq, "SetWindowPos:SWP_HIDEWINDOW:overlapped", FALSE); ok(!IsWindowVisible(hwnd), "window should not be visible at this point\n"); ok(GetActiveWindow() == hwnd, "window should still be active\n");
/* test WM_SETREDRAW on a visible top level window */ ShowWindow(hwnd, SW_SHOW); flush_events(); test_WM_SETREDRAW(hwnd);
trace("testing scroll APIs on a visible top level window %p\n", hwnd); test_scroll_messages(hwnd);
/* test resizing and moving */ SetWindowPos( hwnd, 0, 0, 0, 300, 300, SWP_NOMOVE|SWP_NOACTIVATE ); ok_sequence(WmSWP_ResizeSeq, "SetWindowPos:Resize", FALSE ); flush_events(); flush_sequence(); SetWindowPos( hwnd, 0, 200, 200, 0, 0, SWP_NOSIZE|SWP_NOACTIVATE ); ok_sequence(WmSWP_MoveSeq, "SetWindowPos:Move", FALSE ); flush_events(); flush_sequence(); SetWindowPos( hwnd, 0, 200, 200, 250, 250, SWP_NOZORDER|SWP_NOACTIVATE ); ok_sequence(WmSWP_ResizeNoZOrder, "SetWindowPos:WmSWP_ResizeNoZOrder", FALSE ); flush_events(); flush_sequence();
/* popups don't get WM_GETMINMAXINFO */ SetWindowLongW( hwnd, GWL_STYLE, WS_VISIBLE|WS_POPUP ); SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_FRAMECHANGED); flush_sequence(); SetWindowPos( hwnd, 0, 0, 0, 200, 200, SWP_NOMOVE|SWP_NOACTIVATE ); ok_sequence(WmSWP_ResizePopupSeq, "SetWindowPos:ResizePopup", FALSE );
DestroyWindow(hwnd); ok_sequence(WmDestroyOverlappedSeq, "DestroyWindow:overlapped", FALSE);
/* Test if windows are correctly drawn when first shown */
/* Visible, redraw */ flush_events(); flush_sequence(); hwnd = CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP | WS_VISIBLE, 10, 10, 100, 100, NULL, 0, 0, NULL ); ok (hwnd != 0, "Failed to create popup window\n"); RedrawWindow(hwnd, NULL, NULL, RDW_UPDATENOW); ok_sequence(WmShowPopupFirstDrawSeq_1, "RedrawWindow:show_popup_first_draw_visible", FALSE); DestroyWindow(hwnd);
/* Invisible, show, message */ flush_events(); flush_sequence(); hwnd = CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP, 10, 10, 100, 100, NULL, 0, 0, NULL ); ok (hwnd != 0, "Failed to create popup window\n"); ShowWindow(hwnd, SW_SHOW); SendMessageW(hwnd, WM_PAINT, 0, 0); ok_sequence(WmShowPopupFirstDrawSeq_1, "RedrawWindow:show_popup_first_draw_show", FALSE); DestroyWindow(hwnd);
/* Invisible, show maximized, redraw */ flush_events(); flush_sequence(); hwnd = CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP, 10, 10, 100, 100, NULL, 0, 0, NULL ); ok (hwnd != 0, "Failed to create popup window\n"); ShowWindow(hwnd, SW_SHOWMAXIMIZED); RedrawWindow(hwnd, NULL, NULL, RDW_UPDATENOW); ok_sequence(WmShowPopupFirstDrawSeq_2, "RedrawWindow:show_popup_first_draw_show_maximized", FALSE); DestroyWindow(hwnd);
/* Test SetWindowPos */ test_msg_setpos(WmFirstDrawSetWindowPosSeq1, SWP_SHOWWINDOW, FALSE); test_msg_setpos(WmFirstDrawSetWindowPosSeq2, 0, FALSE); test_msg_setpos(WmFirstDrawSetWindowPosSeq3, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE | SWP_NOZORDER, FALSE);
test_msg_setpos(WmFirstDrawSetWindowPosSeq1, SWP_SHOWWINDOW | SWP_NOSIZE, FALSE); test_msg_setpos(WmFirstDrawSetWindowPosSeq4, SWP_SHOWWINDOW | SWP_NOMOVE, FALSE); test_msg_setpos(WmFirstDrawSetWindowPosSeq3, SWP_SHOWWINDOW | SWP_NOCLIENTSIZE, FALSE); test_msg_setpos(WmFirstDrawSetWindowPosSeq3, SWP_SHOWWINDOW | SWP_NOCLIENTMOVE, FALSE); test_msg_setpos(WmFirstDrawSetWindowPosSeq1, SWP_SHOWWINDOW | SWP_NOZORDER, FALSE);
test_msg_setpos(WmFirstDrawSetWindowPosSeq2, SWP_SHOWWINDOW | SWP_DEFERERASE, FALSE); test_msg_setpos(WmFirstDrawSetWindowPosSeq3, SWP_SHOWWINDOW | SWP_DEFERERASE | SWP_NOCLIENTMOVE, FALSE); test_msg_setpos(WmFirstDrawSetWindowPosSeq3, SWP_SHOWWINDOW | SWP_DEFERERASE | SWP_NOCLIENTSIZE, FALSE); test_msg_setpos(WmFirstDrawSetWindowPosSeq5, SWP_SHOWWINDOW | SWP_DEFERERASE | SWP_NOMOVE, FALSE); test_msg_setpos(WmFirstDrawSetWindowPosSeq2, SWP_SHOWWINDOW | SWP_DEFERERASE | SWP_NOSIZE, FALSE); test_msg_setpos(WmFirstDrawSetWindowPosSeq2, SWP_SHOWWINDOW | SWP_DEFERERASE | SWP_NOZORDER, FALSE);
test_msg_setpos(WmFirstDrawSetWindowPosSeq1, SWP_SHOWWINDOW | SWP_NOCOPYBITS, FALSE); test_msg_setpos(WmFirstDrawSetWindowPosSeq3, SWP_SHOWWINDOW | SWP_NOCOPYBITS | SWP_NOCLIENTMOVE, FALSE); test_msg_setpos(WmFirstDrawSetWindowPosSeq3, SWP_SHOWWINDOW | SWP_NOCOPYBITS | SWP_NOCLIENTSIZE, FALSE); test_msg_setpos(WmFirstDrawSetWindowPosSeq4, SWP_SHOWWINDOW | SWP_NOCOPYBITS | SWP_NOMOVE, FALSE); test_msg_setpos(WmFirstDrawSetWindowPosSeq1, SWP_SHOWWINDOW | SWP_NOCOPYBITS | SWP_NOSIZE, FALSE); test_msg_setpos(WmFirstDrawSetWindowPosSeq1, SWP_SHOWWINDOW | SWP_NOCOPYBITS | SWP_NOZORDER, FALSE);
test_msg_setpos(WmFirstDrawSetWindowPosSeq2, SWP_SHOWWINDOW | SWP_NOREDRAW, FALSE); test_msg_setpos(WmFirstDrawSetWindowPosSeq3, SWP_SHOWWINDOW | SWP_NOREDRAW | SWP_NOCLIENTMOVE, FALSE); test_msg_setpos(WmFirstDrawSetWindowPosSeq3, SWP_SHOWWINDOW | SWP_NOREDRAW | SWP_NOCLIENTSIZE, FALSE); test_msg_setpos(WmFirstDrawSetWindowPosSeq5, SWP_SHOWWINDOW | SWP_NOREDRAW | SWP_NOMOVE, FALSE); test_msg_setpos(WmFirstDrawSetWindowPosSeq2, SWP_SHOWWINDOW | SWP_NOREDRAW | SWP_NOSIZE, FALSE); test_msg_setpos(WmFirstDrawSetWindowPosSeq2, SWP_SHOWWINDOW | SWP_NOREDRAW | SWP_NOZORDER, FALSE);
/* Test SetWindowPos with child windows */ flush_events(); hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 200, 200, 0, 0, 0, NULL); ok (hparent != 0, "Failed to create parent window\n");
hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE, 0, 0, 10, 10, hparent, 0, 0, NULL); ok (hchild != 0, "Failed to create child window\n"); flush_sequence(); SetWindowPos(hparent, NULL, 0, 0, 100, 100, SWP_SHOWWINDOW); ok_sequence(WmFirstDrawChildSeq1, /* Expect no messages for the child */ "SetWindowPos:show_popup_first_show_window_child1", FALSE); DestroyWindow(hchild); DestroyWindow(hparent);
flush_events(); hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN, 100, 100, 200, 200, 0, 0, 0, NULL); ok (hparent != 0, "Failed to create parent window\n");
hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE, 0, 0, 10, 10, hparent, 0, 0, NULL); ok (hchild != 0, "Failed to create child window\n"); flush_sequence(); SetWindowPos(hparent, NULL, 0, 0, 100, 100, SWP_SHOWWINDOW); ok_sequence(WmFirstDrawChildSeq2, /* Expect child to be redrawn */ "SetWindowPos:show_popup_first_show_window_child2", FALSE); DestroyWindow(hchild); DestroyWindow(hparent);
/* Test message sequence for extreme position and size */
flush_sequence(); hwnd = CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP | WS_VISIBLE, -10, -10, 10000, 10000, NULL, 0, 0, NULL ); ok (hwnd != 0, "Failed to create popup window\n"); ok_sequence(WmShowPopupExtremeLocationSeq, "RedrawWindow:show_popup_extreme_location", FALSE); DestroyWindow(hwnd);
/* Test child windows */
hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 200, 200, 0, 0, 0, NULL); ok (hparent != 0, "Failed to create parent window\n"); flush_sequence();
hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_MAXIMIZE, 0, 0, 10, 10, hparent, 0, 0, NULL); ok (hchild != 0, "Failed to create child window\n"); ok_sequence(WmCreateMaximizedChildSeq, "CreateWindow:maximized child", FALSE); DestroyWindow(hchild); flush_sequence();
/* visible child window with a caption */ hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE | WS_CAPTION, 0, 0, 10, 10, hparent, 0, 0, NULL); ok (hchild != 0, "Failed to create child window\n"); ok_sequence(WmCreateVisibleChildSeq, "CreateWindow:visible child", FALSE);
trace("testing scroll APIs on a visible child window %p\n", hchild); test_scroll_messages(hchild);
SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE); ok_sequence(WmShowChildSeq_4, "SetWindowPos(SWP_SHOWWINDOW):child with a caption", FALSE);
DestroyWindow(hchild); flush_sequence();
hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 0, 0, 10, 10, hparent, 0, 0, NULL); ok (hchild != 0, "Failed to create child window\n"); ok_sequence(WmCreateChildSeq, "CreateWindow:child", FALSE); hchild2 = CreateWindowExA(0, "SimpleWindowClass", "Test child2", WS_CHILD, 100, 100, 50, 50, hparent, 0, 0, NULL); ok (hchild2 != 0, "Failed to create child2 window\n"); flush_sequence();
hbutton = CreateWindowExA(0, "TestWindowClass", "Test button", WS_CHILD, 0, 100, 50, 50, hchild, 0, 0, NULL); ok (hbutton != 0, "Failed to create button window\n");
/* test WM_SETREDRAW on a not visible child window */ test_WM_SETREDRAW(hchild);
ShowWindow(hchild, SW_SHOW); ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):child", FALSE);
/* check parent messages too */ log_all_parent_messages++; ShowWindow(hchild, SW_HIDE); ok_sequence(WmHideChildSeq2, "ShowWindow(SW_HIDE):child", FALSE); log_all_parent_messages--;
ShowWindow(hchild, SW_SHOW); ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):child", FALSE);
ShowWindow(hchild, SW_HIDE); ok_sequence(WmHideChildSeq, "ShowWindow(SW_HIDE):child", FALSE);
ShowWindow(hchild, SW_SHOW); ok_sequence(WmShowChildSeq, "ShowWindow(SW_SHOW):child", FALSE);
/* test WM_SETREDRAW on a visible child window */ test_WM_SETREDRAW(hchild);
log_all_parent_messages++; MoveWindow(hchild, 10, 10, 20, 20, TRUE); ok_sequence(WmResizingChildWithMoveWindowSeq, "MoveWindow:child", FALSE); log_all_parent_messages--;
ShowWindow(hchild, SW_HIDE); flush_sequence(); SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE); ok_sequence(WmShowChildSeq_2, "SetWindowPos:show_child_2", FALSE);
ShowWindow(hchild, SW_HIDE); flush_sequence(); SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE); ok_sequence(WmShowChildSeq_3, "SetWindowPos:show_child_3", FALSE);
/* DestroyWindow sequence below expects that a child has focus */ SetFocus(hchild); flush_sequence();
DestroyWindow(hchild); ok_sequence(WmDestroyChildSeq, "DestroyWindow:child", FALSE); DestroyWindow(hchild2); DestroyWindow(hbutton);
flush_sequence(); hchild = CreateWindowExA(0, "TestWindowClass", "Test Child Popup", WS_CHILD | WS_POPUP, 0, 0, 100, 100, hparent, 0, 0, NULL); ok (hchild != 0, "Failed to create child popup window\n"); ok_sequence(WmCreateChildPopupSeq, "CreateWindow:child_popup", FALSE); DestroyWindow(hchild);
/* test what happens to a window which sets WS_VISIBLE in WM_CREATE */ flush_sequence(); hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP, 0, 0, 100, 100, hparent, 0, 0, NULL); ok (hchild != 0, "Failed to create popup window\n"); ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup", FALSE); ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n"); flush_sequence(); ShowWindow(hchild, SW_SHOW); ok_sequence(WmEmptySeq, "ShowWindow:show_visible_popup", FALSE); flush_sequence(); SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER); ok_sequence(WmShowVisiblePopupSeq_2, "SetWindowPos:show_visible_popup_2", FALSE); flush_sequence(); SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE); ok_sequence(WmShowVisiblePopupSeq_3, "SetWindowPos:show_visible_popup_3", FALSE); DestroyWindow(hchild);
/* this time add WS_VISIBLE for CreateWindowEx, but this fact actually * changes nothing in message sequences. */ flush_sequence(); hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP | WS_VISIBLE, 0, 0, 100, 100, hparent, 0, 0, NULL); ok (hchild != 0, "Failed to create popup window\n"); ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup", FALSE); ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n"); flush_sequence(); ShowWindow(hchild, SW_SHOW); ok_sequence(WmEmptySeq, "ShowWindow:show_visible_popup", FALSE); flush_sequence(); SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER); ok_sequence(WmShowVisiblePopupSeq_2, "SetWindowPos:show_visible_popup_2", FALSE); DestroyWindow(hchild);
flush_sequence(); hwnd = CreateWindowExA(WS_EX_DLGMODALFRAME, "TestDialogClass", NULL, WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_DLGFRAME, 0, 0, 100, 100, hparent, 0, 0, NULL); ok(hwnd != 0, "Failed to create custom dialog window\n"); ok_sequence(WmCreateCustomDialogSeq, "CreateCustomDialog", TRUE);
if(0) { trace("testing scroll APIs on a visible dialog %p\n", hwnd); test_scroll_messages(hwnd); }
flush_sequence();
test_def_id = TRUE; SendMessageA(hwnd, WM_NULL, 0, 0);
flush_sequence(); after_end_dialog = TRUE; EndDialog( hwnd, 0 ); ok_sequence(WmEndCustomDialogSeq, "EndCustomDialog", FALSE);
DestroyWindow(hwnd); after_end_dialog = FALSE; test_def_id = FALSE;
ok(GetCursorPos(&pos), "GetCursorPos failed\n"); ok(SetCursorPos(109, 109), "SetCursorPos failed\n");
hwnd = CreateWindowExA(0, "TestDialogClass", NULL, WS_POPUP|WS_CHILD, 0, 0, 100, 100, 0, 0, GetModuleHandleA(0), NULL); ok(hwnd != 0, "Failed to create custom dialog window\n"); flush_sequence(); trace("call ShowWindow(%p, SW_SHOW)\n", hwnd); ShowWindow(hwnd, SW_SHOW); ok_sequence(WmShowCustomDialogSeq, "ShowCustomDialog", TRUE);
flush_events(); flush_sequence(); ret = DrawMenuBar(hwnd); ok(ret, "DrawMenuBar failed: %d\n", GetLastError()); flush_events(); ok_sequence(WmDrawMenuBarSeq, "DrawMenuBar", FALSE); ok(SetCursorPos(pos.x, pos.y), "SetCursorPos failed\n");
DestroyWindow(hwnd);
hwnd = CreateWindowExA(0, "TestDialogClass", NULL, WS_CHILD|WS_VISIBLE, 0, 0, 100, 100, hparent, 0, GetModuleHandleA(0), NULL); ok(hwnd != 0, "Failed to create custom dialog window\n"); flush_events(); flush_sequence(); ret = DrawMenuBar(hwnd); ok(ret, "DrawMenuBar failed: %d\n", GetLastError()); flush_events(); ok_sequence(WmEmptySeq, "DrawMenuBar for a child window", FALSE);
DestroyWindow(hwnd);
flush_sequence(); DialogBoxA( 0, "TEST_DIALOG", hparent, TestModalDlgProcA ); ok_sequence(WmModalDialogSeq, "ModalDialog", TRUE);
DestroyWindow(hparent); flush_sequence();
/* Message sequence for SetMenu */ ok(!DrawMenuBar(hwnd), "DrawMenuBar should return FALSE for a destroyed window\n"); ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "last error is %d\n", GetLastError()); ok_sequence(WmEmptySeq, "DrawMenuBar for a window without a menu", FALSE);
hmenu = CreateMenu(); ok (hmenu != 0, "Failed to create menu\n"); ok (InsertMenuA(hmenu, -1, MF_BYPOSITION, 0x1000, "foo"), "InsertMenu failed\n"); hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW, 100, 100, 200, 200, 0, hmenu, 0, NULL); ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped", FALSE); ok (SetMenu(hwnd, 0), "SetMenu\n"); ok_sequence(WmSetMenuNonVisibleSizeChangeSeq, "SetMenu:NonVisibleSizeChange", FALSE); ok (SetMenu(hwnd, 0), "SetMenu\n"); ok_sequence(WmSetMenuNonVisibleNoSizeChangeSeq, "SetMenu:NonVisibleNoSizeChange", FALSE); ShowWindow(hwnd, SW_SHOW); UpdateWindow( hwnd ); flush_events(); flush_sequence(); ok (SetMenu(hwnd, 0), "SetMenu\n"); ok_sequence(WmSetMenuVisibleNoSizeChangeSeq, "SetMenu:VisibleNoSizeChange", FALSE); ok (SetMenu(hwnd, hmenu), "SetMenu\n"); ok_sequence(WmSetMenuVisibleSizeChangeSeq, "SetMenu:VisibleSizeChange", FALSE);
UpdateWindow( hwnd ); flush_events(); flush_sequence(); ok(DrawMenuBar(hwnd), "DrawMenuBar\n"); flush_events(); ok_sequence(WmDrawMenuBarSeq, "DrawMenuBar", FALSE);
DestroyWindow(hwnd); flush_sequence();
/* Message sequence for EnableWindow */ hparent = CreateWindowExA(0, "TestWindowClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 200, 200, 0, 0, 0, NULL); ok (hparent != 0, "Failed to create parent window\n"); hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE, 0, 0, 10, 10, hparent, 0, 0, NULL); ok (hchild != 0, "Failed to create child window\n");
SetFocus(hchild); flush_events(); flush_sequence();
EnableWindow(hparent, FALSE); ok_sequence(WmEnableWindowSeq_1, "EnableWindow(FALSE)", FALSE);
EnableWindow(hparent, FALSE); ok_sequence(WmEnableWindowSeq_2, "EnableWindow(FALSE)", FALSE);
EnableWindow(hparent, TRUE); ok_sequence(WmEnableWindowSeq_3, "EnableWindow(TRUE)", FALSE);
EnableWindow(hparent, TRUE); ok_sequence(WmEnableWindowSeq_4, "EnableWindow(TRUE)", FALSE);
flush_events(); flush_sequence();
test_MsgWaitForMultipleObjects(hparent); test_WM_DEVICECHANGE(hparent);
/* the following test causes an exception in user.exe under win9x */ if (!PostMessageW( hparent, WM_USER, 0, 0 )) { DestroyWindow(hparent); flush_sequence(); return; } PostMessageW( hparent, WM_USER+1, 0, 0 ); /* PeekMessage(NULL) fails, but still removes the message */ SetLastError(0xdeadbeef); ok( !PeekMessageW( NULL, 0, 0, 0, PM_REMOVE ), "PeekMessage(NULL) should fail\n" ); ok( GetLastError() == ERROR_NOACCESS || /* Win2k */ GetLastError() == 0xdeadbeef, /* NT4 */ "last error is %d\n", GetLastError() ); ok( PeekMessageW( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n" ); ok( msg.message == WM_USER+1, "got %x instead of WM_USER+1\n", msg.message );
DestroyWindow(hchild); DestroyWindow(hparent); flush_sequence();
/* Message sequences for WM_SETICON */ trace("testing WM_SETICON\n"); hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0, NULL, NULL, 0); ShowWindow(hwnd, SW_SHOW); UpdateWindow(hwnd); flush_events(); flush_sequence(); SendMessageA(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)LoadIconA(0, (LPCSTR)IDI_APPLICATION)); ok_sequence(WmSetIcon_1, "WM_SETICON for shown window with caption", FALSE);
ShowWindow(hwnd, SW_HIDE); flush_events(); flush_sequence(); SendMessageA(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)LoadIconA(0, (LPCSTR)IDI_APPLICATION)); ok_sequence(WmSetIcon_2, "WM_SETICON for hidden window with caption", FALSE); DestroyWindow(hwnd); flush_sequence();
hwnd = CreateWindowExA(0, "TestPopupClass", NULL, WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0, NULL, NULL, 0); ShowWindow(hwnd, SW_SHOW); UpdateWindow(hwnd); flush_events(); flush_sequence(); SendMessageA(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)LoadIconA(0, (LPCSTR)IDI_APPLICATION)); ok_sequence(WmSetIcon_2, "WM_SETICON for shown window without caption", FALSE);
ShowWindow(hwnd, SW_HIDE); flush_events(); flush_sequence(); SendMessageA(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)LoadIconA(0, (LPCSTR)IDI_APPLICATION)); ok_sequence(WmSetIcon_2, "WM_SETICON for hidden window without caption", FALSE);
flush_sequence(); res = SendMessageA(hwnd, 0x3B, 0x8000000b, 0); if (!res) { todo_wine win_skip( "Message 0x3b not supported\n" ); goto done; } ok_sequence(WmInitEndSession, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x8000000b", TRUE); ok(res == 1, "SendMessage(hwnd, 0x3B, 0x8000000b, 0) should have returned 1 instead of %ld\n", res); res = SendMessageA(hwnd, 0x3B, 0x0000000b, 0); ok_sequence(WmInitEndSession_2, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x0000000b", TRUE); ok(res == 1, "SendMessage(hwnd, 0x3B, 0x0000000b, 0) should have returned 1 instead of %ld\n", res); res = SendMessageA(hwnd, 0x3B, 0x0000000f, 0); ok_sequence(WmInitEndSession_2, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x0000000f", TRUE); ok(res == 1, "SendMessage(hwnd, 0x3B, 0x0000000f, 0) should have returned 1 instead of %ld\n", res);
flush_sequence(); res = SendMessageA(hwnd, 0x3B, 0x80000008, 0); ok_sequence(WmInitEndSession_3, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000008", TRUE); ok(res == 2, "SendMessage(hwnd, 0x3B, 0x80000008, 0) should have returned 2 instead of %ld\n", res); res = SendMessageA(hwnd, 0x3B, 0x00000008, 0); ok_sequence(WmInitEndSession_4, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x00000008", TRUE); ok(res == 2, "SendMessage(hwnd, 0x3B, 0x00000008, 0) should have returned 2 instead of %ld\n", res);
res = SendMessageA(hwnd, 0x3B, 0x80000004, 0); ok_sequence(WmInitEndSession_3, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000004", TRUE); ok(res == 2, "SendMessage(hwnd, 0x3B, 0x80000004, 0) should have returned 2 instead of %ld\n", res);
res = SendMessageA(hwnd, 0x3B, 0x80000001, 0); ok_sequence(WmInitEndSession_5, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000001", TRUE); ok(res == 2, "SendMessage(hwnd, 0x3B, 0x80000001, 0) should have returned 2 instead of %ld\n", res);
done: DestroyWindow(hwnd); flush_sequence();}
static void test_setwindowpos(void){ HWND hwnd; RECT rc; LRESULT res; const INT winX = 100; const INT winY = 100; const INT sysX = GetSystemMetrics(SM_CXMINTRACK);
hwnd = CreateWindowExA(0, "TestWindowClass", NULL, 0, 0, 0, winX, winY, 0, NULL, NULL, 0);
GetWindowRect(hwnd, &rc); expect(sysX, rc.right); expect(winY, rc.bottom);
flush_events(); flush_sequence(); res = SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, winX, winY, 0); ok_sequence(WmZOrder, "Z-Order", TRUE); ok(res == TRUE, "SetWindowPos expected TRUE, got %ld\n", res);
GetWindowRect(hwnd, &rc); expect(sysX, rc.right); expect(winY, rc.bottom); DestroyWindow(hwnd);}
static void invisible_parent_tests(void){ HWND hparent, hchild;
hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW, 100, 100, 200, 200, 0, 0, 0, NULL); ok (hparent != 0, "Failed to create parent window\n"); flush_sequence();
/* test showing child with hidden parent */
hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 0, 0, 10, 10, hparent, 0, 0, NULL); ok (hchild != 0, "Failed to create child window\n"); ok_sequence(WmCreateChildSeq, "CreateWindow:child", FALSE);
ShowWindow( hchild, SW_MINIMIZE ); ok_sequence(WmShowChildInvisibleParentSeq_1, "ShowWindow(SW_MINIMIZE) child with invisible parent", FALSE); ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
/* repeat */ flush_events(); flush_sequence(); ShowWindow( hchild, SW_MINIMIZE ); ok_sequence(WmShowChildInvisibleParentSeq_1r, "ShowWindow(SW_MINIMIZE) child with invisible parent", FALSE);
DestroyWindow(hchild); hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 0, 0, 10, 10, hparent, 0, 0, NULL); flush_sequence();
ShowWindow( hchild, SW_MAXIMIZE ); ok_sequence(WmShowChildInvisibleParentSeq_2, "ShowWindow(SW_MAXIMIZE) child with invisible parent", FALSE); ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
/* repeat */ flush_events(); flush_sequence(); ShowWindow( hchild, SW_MAXIMIZE ); ok_sequence(WmShowChildInvisibleParentSeq_2r, "ShowWindow(SW_MAXIMIZE) child with invisible parent", FALSE);
DestroyWindow(hchild); hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 0, 0, 10, 10, hparent, 0, 0, NULL); flush_sequence();
ShowWindow( hchild, SW_RESTORE ); ok_sequence(WmShowChildInvisibleParentSeq_5, "ShowWindow(SW_RESTORE) child with invisible parent", FALSE); ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
DestroyWindow(hchild); hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 0, 0, 10, 10, hparent, 0, 0, NULL); flush_sequence();
ShowWindow( hchild, SW_SHOWMINIMIZED ); ok_sequence(WmShowChildInvisibleParentSeq_3, "ShowWindow(SW_SHOWMINIMIZED) child with invisible parent", FALSE); ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
/* repeat */ flush_events(); flush_sequence(); ShowWindow( hchild, SW_SHOWMINIMIZED ); ok_sequence(WmShowChildInvisibleParentSeq_3r, "ShowWindow(SW_SHOWMINIMIZED) child with invisible parent", FALSE);
DestroyWindow(hchild); hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 0, 0, 10, 10, hparent, 0, 0, NULL); flush_sequence();
/* same as ShowWindow( hchild, SW_MAXIMIZE ); */ ShowWindow( hchild, SW_SHOWMAXIMIZED ); ok_sequence(WmShowChildInvisibleParentSeq_2, "ShowWindow(SW_SHOWMAXIMIZED) child with invisible parent", FALSE); ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
DestroyWindow(hchild); hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 0, 0, 10, 10, hparent, 0, 0, NULL); flush_sequence();
ShowWindow( hchild, SW_SHOWMINNOACTIVE ); ok_sequence(WmShowChildInvisibleParentSeq_4, "ShowWindow(SW_SHOWMINNOACTIVE) child with invisible parent", FALSE); ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
/* repeat */ flush_events(); flush_sequence(); ShowWindow( hchild, SW_SHOWMINNOACTIVE ); ok_sequence(WmShowChildInvisibleParentSeq_4r, "ShowWindow(SW_SHOWMINNOACTIVE) child with invisible parent", FALSE);
DestroyWindow(hchild); hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 0, 0, 10, 10, hparent, 0, 0, NULL); flush_sequence();
/* FIXME: looks like XP SP2 doesn't know about SW_FORCEMINIMIZE at all */ ShowWindow( hchild, SW_FORCEMINIMIZE ); ok_sequence(WmEmptySeq, "ShowWindow(SW_FORCEMINIMIZE) child with invisible parent", TRUE);todo_wine { ok(!(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should be not set\n");} ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
DestroyWindow(hchild); hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 0, 0, 10, 10, hparent, 0, 0, NULL); flush_sequence();
ShowWindow( hchild, SW_SHOWNA ); ok_sequence(WmShowChildInvisibleParentSeq_5, "ShowWindow(SW_SHOWNA) child with invisible parent", FALSE); ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
/* repeat */ flush_events(); flush_sequence(); ShowWindow( hchild, SW_SHOWNA ); ok_sequence(WmShowChildInvisibleParentSeq_5, "ShowWindow(SW_SHOWNA) child with invisible parent", FALSE);
DestroyWindow(hchild); hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD, 0, 0, 10, 10, hparent, 0, 0, NULL); flush_sequence();
ShowWindow( hchild, SW_SHOW ); ok_sequence(WmShowChildInvisibleParentSeq_5, "ShowWindow(SW_SHOW) child with invisible parent", FALSE); ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
/* repeat */ flush_events(); flush_sequence(); ShowWindow( hchild, SW_SHOW ); ok_sequence(WmEmptySeq, "ShowWindow(SW_SHOW) child with invisible parent", FALSE);
ShowWindow( hchild, SW_HIDE ); ok_sequence(WmHideChildInvisibleParentSeq, "ShowWindow:hide child with invisible parent", FALSE); ok(!(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should be not set\n"); ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER); ok_sequence(WmShowChildInvisibleParentSeq_6, "SetWindowPos:show child with invisible parent", FALSE); ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
SetWindowPos(hchild, 0,0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER); ok_sequence(WmHideChildInvisibleParentSeq_2, "SetWindowPos:hide child with invisible parent", FALSE); ok(!(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should not be set\n"); ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER); flush_sequence(); DestroyWindow(hchild); ok_sequence(WmDestroyInvisibleChildSeq, "DestroyInvisibleChildSeq", FALSE);
DestroyWindow(hparent); flush_sequence();}
/****************** button message test *************************/#define ID_BUTTON 0x000e
static const struct message WmSetFocusButtonSeq[] ={ { HCBT_SETFOCUS, hook }, { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|wparam, 0 }, { WM_CTLCOLORBTN, sent|parent }, { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_SETFOCUS) }, { WM_APP, sent|wparam|lparam, 0, 0 }, { 0 }};static const struct message WmKillFocusButtonSeq[] ={ { HCBT_SETFOCUS, hook }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_KILLFOCUS, sent|wparam, 0 }, { WM_CTLCOLORBTN, sent|parent }, { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_KILLFOCUS) }, { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 1 }, { WM_APP, sent|wparam|lparam, 0, 0 }, { WM_PAINT, sent }, { WM_CTLCOLORBTN, sent|parent }, { 0 }};static const struct message WmSetFocusStaticSeq[] ={ { HCBT_SETFOCUS, hook }, { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|wparam, 0 }, { WM_CTLCOLORSTATIC, sent|parent }, { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_SETFOCUS) }, { WM_COMMAND, sent|wparam|parent|optional, MAKEWPARAM(ID_BUTTON, BN_CLICKED) }, /* radio button */ { WM_APP, sent|wparam|lparam, 0, 0 }, { 0 }};static const struct message WmKillFocusStaticSeq[] ={ { HCBT_SETFOCUS, hook }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_KILLFOCUS, sent|wparam, 0 }, { WM_CTLCOLORSTATIC, sent|parent }, { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_KILLFOCUS) }, { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 1 }, { WM_APP, sent|wparam|lparam, 0, 0 }, { WM_PAINT, sent }, { WM_CTLCOLORSTATIC, sent|parent }, { 0 }};static const struct message WmSetFocusOwnerdrawSeq[] ={ { HCBT_SETFOCUS, hook }, { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|wparam, 0 }, { WM_CTLCOLORBTN, sent|parent }, { WM_DRAWITEM, sent|wparam|lparam|parent, ID_BUTTON, 0x001040e4 }, { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_SETFOCUS) }, { WM_APP, sent|wparam|lparam, 0, 0 }, { 0 }};static const struct message WmKillFocusOwnerdrawSeq[] ={ { HCBT_SETFOCUS, hook }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_KILLFOCUS, sent|wparam, 0 }, { WM_CTLCOLORBTN, sent|parent }, { WM_DRAWITEM, sent|wparam|lparam|parent, ID_BUTTON, 0x000040e4 }, { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_KILLFOCUS) }, { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 1 }, { WM_APP, sent|wparam|lparam, 0, 0 }, { WM_PAINT, sent }, { WM_CTLCOLORBTN, sent|parent }, { WM_DRAWITEM, sent|wparam|lparam|parent, ID_BUTTON, 0x000010e4 }, { 0 }};static const struct message WmLButtonDownSeq[] ={ { WM_LBUTTONDOWN, sent|wparam|lparam, 0, 0 }, { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, { HCBT_SETFOCUS, hook }, { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, { WM_CTLCOLORBTN, sent|defwinproc }, { BM_SETSTATE, sent|wparam|defwinproc, TRUE }, { WM_CTLCOLORBTN, sent|defwinproc }, { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { 0 }};static const struct message WmLButtonDownStaticSeq[] ={ { WM_LBUTTONDOWN, sent|wparam|lparam, 0, 0 }, { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, { HCBT_SETFOCUS, hook }, { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, { WM_CTLCOLORSTATIC, sent|defwinproc }, { BM_SETSTATE, sent|wparam|defwinproc, TRUE }, { WM_CTLCOLORSTATIC, sent|defwinproc }, { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { 0 }};static const struct message WmLButtonUpSeq[] ={ { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 }, { BM_SETSTATE, sent|wparam|defwinproc, FALSE }, { WM_CTLCOLORBTN, sent|defwinproc }, { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 }, { WM_CAPTURECHANGED, sent|wparam|defwinproc, 0 }, { 0 }};static const struct message WmLButtonUpStaticSeq[] ={ { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 }, { BM_SETSTATE, sent|wparam|defwinproc, FALSE }, { WM_CTLCOLORSTATIC, sent|defwinproc }, { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 }, { WM_CAPTURECHANGED, sent|wparam|defwinproc, 0 }, { 0 }};static const struct message WmLButtonUpAutoSeq[] ={ { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 }, { BM_SETSTATE, sent|wparam|defwinproc, FALSE }, { WM_CTLCOLORSTATIC, sent|defwinproc }, { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 }, { BM_SETCHECK, sent|defwinproc }, { WM_CTLCOLORSTATIC, sent|defwinproc, 0, 0 }, { WM_CAPTURECHANGED, sent|wparam|defwinproc, 0 }, { 0 }};static const struct message WmLButtonUpBrokenSeq[] ={ { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 }, { 0 }};static const struct message WmSetFontButtonSeq[] ={ { WM_SETFONT, sent }, { WM_PAINT, sent }, { WM_ERASEBKGND, sent|defwinproc|optional }, { WM_CTLCOLORBTN, sent|defwinproc }, { WM_CTLCOLORBTN, sent|defwinproc|optional }, /* FIXME: Wine sends it twice for BS_OWNERDRAW */ { 0 }};static const struct message WmSetFontStaticSeq[] ={ { WM_SETFONT, sent }, { WM_PAINT, sent }, { WM_ERASEBKGND, sent|defwinproc|optional }, { WM_CTLCOLORSTATIC, sent|defwinproc }, { 0 }};static const struct message WmSetTextButtonSeq[] ={ { WM_SETTEXT, sent }, { WM_CTLCOLORBTN, sent|parent }, { WM_CTLCOLORBTN, sent|parent }, { WM_COMMAND, sent|parent|optional }, { WM_DRAWITEM, sent|parent|optional }, { 0 }};static const struct message WmSetTextStaticSeq[] ={ { WM_SETTEXT, sent }, { WM_CTLCOLORSTATIC, sent|parent }, { WM_CTLCOLORSTATIC, sent|parent }, { 0 }};static const struct message WmSetTextGroupSeq[] ={ { WM_SETTEXT, sent }, { WM_CTLCOLORSTATIC, sent|parent }, { WM_CTLCOLORSTATIC, sent|parent|optional }, /* FIXME: Missing in Wine */ { WM_CTLCOLORSTATIC, sent|parent|optional }, /* FIXME: Missing in Wine */ { 0 }};static const struct message WmSetTextInvisibleSeq[] ={ { WM_SETTEXT, sent }, { 0 }};static const struct message WmSetStyleButtonSeq[] ={ { BM_SETSTYLE, sent }, { WM_APP, sent|wparam|lparam, 0, 0 }, { WM_PAINT, sent }, { WM_NCPAINT, sent|defwinproc|optional }, /* FIXME: Wine sends it */ { WM_ERASEBKGND, sent|defwinproc|optional }, /* Win9x doesn't send it */ { WM_CTLCOLORBTN, sent|parent }, { 0 }};static const struct message WmSetStyleStaticSeq[] ={ { BM_SETSTYLE, sent }, { WM_APP, sent|wparam|lparam, 0, 0 }, { WM_PAINT, sent }, { WM_NCPAINT, sent|defwinproc|optional }, /* FIXME: Wine sends it */ { WM_ERASEBKGND, sent|defwinproc|optional }, /* Win9x doesn't send it */ { WM_CTLCOLORSTATIC, sent|parent }, { 0 }};static const struct message WmSetStyleUserSeq[] ={ { BM_SETSTYLE, sent }, { WM_APP, sent|wparam|lparam, 0, 0 }, { WM_PAINT, sent }, { WM_NCPAINT, sent|defwinproc|optional }, /* FIXME: Wine sends it */ { WM_ERASEBKGND, sent|defwinproc|optional }, /* Win9x doesn't send it */ { WM_CTLCOLORBTN, sent|parent }, { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_PAINT) }, { 0 }};static const struct message WmSetStyleOwnerdrawSeq[] ={ { BM_SETSTYLE, sent }, { WM_APP, sent|wparam|lparam, 0, 0 }, { WM_PAINT, sent }, { WM_NCPAINT, sent|optional }, /* FIXME: Wine sends it */ { WM_ERASEBKGND, sent|defwinproc|optional }, /* Win9x doesn't send it */ { WM_CTLCOLORBTN, sent|parent }, { WM_CTLCOLORBTN, sent|parent|optional }, /* Win9x doesn't send it */ { WM_DRAWITEM, sent|wparam|lparam|parent, ID_BUTTON, 0x000010e4 }, { 0 }};static const struct message WmSetStateButtonSeq[] ={ { BM_SETSTATE, sent }, { WM_CTLCOLORBTN, sent|parent }, { WM_APP, sent|wparam|lparam, 0, 0 }, { 0 }};static const struct message WmSetStateStaticSeq[] ={ { BM_SETSTATE, sent }, { WM_CTLCOLORSTATIC, sent|parent }, { WM_APP, sent|wparam|lparam, 0, 0 }, { 0 }};static const struct message WmSetStateUserSeq[] ={ { BM_SETSTATE, sent }, { WM_CTLCOLORBTN, sent|parent }, { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_HILITE) }, { WM_APP, sent|wparam|lparam, 0, 0 }, { 0 }};static const struct message WmSetStateOwnerdrawSeq[] ={ { BM_SETSTATE, sent }, { WM_CTLCOLORBTN, sent|parent }, { WM_DRAWITEM, sent|wparam|lparam|parent, ID_BUTTON, 0x000120e4 }, { WM_APP, sent|wparam|lparam, 0, 0 }, { 0 }};static const struct message WmClearStateButtonSeq[] ={ { BM_SETSTATE, sent }, { WM_CTLCOLORBTN, sent|parent }, { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_UNHILITE) }, { WM_APP, sent|wparam|lparam, 0, 0 }, { 0 }};static const struct message WmDisableButtonSeq[] ={ { WM_LBUTTONDOWN, sent }, { BM_SETSTATE, sent|defwinproc }, { WM_CTLCOLORSTATIC, sent|defwinproc|optional }, { WM_CTLCOLORBTN, sent|optional }, { WM_LBUTTONUP, sent }, { BM_SETSTATE, sent|defwinproc }, { WM_CTLCOLORBTN, sent|defwinproc|optional }, { WM_CTLCOLORSTATIC, sent|defwinproc|optional }, { BM_SETCHECK, sent|defwinproc|optional }, { WM_CTLCOLORBTN, sent|optional }, { WM_CTLCOLORSTATIC, sent|defwinproc|optional }, { WM_CAPTURECHANGED, sent|defwinproc }, { WM_COMMAND, sent }, { 0 }};static const struct message WmClearStateOwnerdrawSeq[] ={ { BM_SETSTATE, sent }, { WM_CTLCOLORBTN, sent|parent }, { WM_DRAWITEM, sent|wparam|lparam|parent, ID_BUTTON, 0x000020e4 }, { WM_APP, sent|wparam|lparam, 0, 0 }, { 0 }};static const struct message WmSetCheckIgnoredSeq[] ={ { BM_SETCHECK, sent }, { WM_APP, sent|wparam|lparam, 0, 0 }, { 0 }};static const struct message WmSetCheckStaticSeq[] ={ { BM_SETCHECK, sent }, { WM_CTLCOLORSTATIC, sent|parent }, { WM_APP, sent|wparam|lparam, 0, 0 }, { 0 }};
static WNDPROC old_button_proc;
static LRESULT CALLBACK button_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ static LONG defwndproc_counter = 0; LRESULT ret; struct recvd_message msg;
if (ignore_message( message )) return 0;
switch (message) { case WM_SYNCPAINT: break; case BM_SETSTATE: if (GetCapture()) ok(GetCapture() == hwnd, "GetCapture() = %p\n", GetCapture());
lParam = (ULONG_PTR)GetMenu(hwnd); goto log_it;
case WM_GETDLGCODE: if (lParam) { MSG *msg = (MSG *)lParam; lParam = MAKELPARAM(msg->message, msg->wParam); } wParam = (ULONG_PTR)GetMenu(hwnd); goto log_it;
case BM_SETCHECK: case BM_GETCHECK: lParam = (ULONG_PTR)GetMenu(hwnd); /* fall through */log_it: default: msg.hwnd = hwnd; msg.message = message; msg.flags = sent|wparam|lparam; if (defwndproc_counter) msg.flags |= defwinproc; msg.wParam = wParam; msg.lParam = lParam; msg.descr = "button"; add_message(&msg); }
defwndproc_counter++; ret = CallWindowProcA(old_button_proc, hwnd, message, wParam, lParam); defwndproc_counter--;
return ret;}
static void subclass_button(void){ WNDCLASSA cls;
if (!GetClassInfoA(0, "button", &cls)) assert(0);
old_button_proc = cls.lpfnWndProc;
cls.hInstance = GetModuleHandleA(NULL); cls.lpfnWndProc = button_hook_proc; cls.lpszClassName = "my_button_class"; UnregisterClassA(cls.lpszClassName, cls.hInstance); if (!RegisterClassA(&cls)) assert(0);}
static void test_button_messages(void){ static const struct { DWORD style; DWORD dlg_code; const struct message *setfocus; const struct message *killfocus; const struct message *setstyle; const struct message *setstate; const struct message *clearstate; const struct message *setcheck; const struct message *lbuttondown; const struct message *lbuttonup; const struct message *setfont; const struct message *settext; } button[] = { { BS_PUSHBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON, WmSetFocusButtonSeq, WmKillFocusButtonSeq, WmSetStyleButtonSeq, WmSetStateButtonSeq, WmSetStateButtonSeq, WmSetCheckIgnoredSeq, WmLButtonDownSeq, WmLButtonUpSeq, WmSetFontButtonSeq, WmSetTextButtonSeq }, { BS_DEFPUSHBUTTON, DLGC_BUTTON | DLGC_DEFPUSHBUTTON, WmSetFocusButtonSeq, WmKillFocusButtonSeq, WmSetStyleButtonSeq, WmSetStateButtonSeq, WmSetStateButtonSeq, WmSetCheckIgnoredSeq, WmLButtonDownSeq, WmLButtonUpSeq, WmSetFontButtonSeq, WmSetTextButtonSeq }, { BS_CHECKBOX, DLGC_BUTTON, WmSetFocusStaticSeq, WmKillFocusStaticSeq, WmSetStyleStaticSeq, WmSetStateStaticSeq, WmSetStateStaticSeq, WmSetCheckStaticSeq, WmLButtonDownStaticSeq, WmLButtonUpStaticSeq, WmSetFontStaticSeq, WmSetTextStaticSeq }, { BS_AUTOCHECKBOX, DLGC_BUTTON, WmSetFocusStaticSeq, WmKillFocusStaticSeq, WmSetStyleStaticSeq, WmSetStateStaticSeq, WmSetStateStaticSeq, WmSetCheckStaticSeq, WmLButtonDownStaticSeq, WmLButtonUpAutoSeq, WmSetFontStaticSeq, WmSetTextStaticSeq }, { BS_RADIOBUTTON, DLGC_BUTTON | DLGC_RADIOBUTTON, WmSetFocusStaticSeq, WmKillFocusStaticSeq, WmSetStyleStaticSeq, WmSetStateStaticSeq, WmSetStateStaticSeq, WmSetCheckStaticSeq, WmLButtonDownStaticSeq, WmLButtonUpStaticSeq, WmSetFontStaticSeq, WmSetTextStaticSeq }, { BS_3STATE, DLGC_BUTTON, WmSetFocusStaticSeq, WmKillFocusStaticSeq, WmSetStyleStaticSeq, WmSetStateStaticSeq, WmSetStateStaticSeq, WmSetCheckStaticSeq, WmLButtonDownStaticSeq, WmLButtonUpStaticSeq, WmSetFontStaticSeq, WmSetTextStaticSeq }, { BS_AUTO3STATE, DLGC_BUTTON, WmSetFocusStaticSeq, WmKillFocusStaticSeq, WmSetStyleStaticSeq, WmSetStateStaticSeq, WmSetStateStaticSeq, WmSetCheckStaticSeq, WmLButtonDownStaticSeq, WmLButtonUpAutoSeq, WmSetFontStaticSeq, WmSetTextStaticSeq }, { BS_GROUPBOX, DLGC_STATIC, WmSetFocusStaticSeq, WmKillFocusStaticSeq, WmSetStyleStaticSeq, WmSetStateStaticSeq, WmSetStateStaticSeq, WmSetCheckIgnoredSeq, WmLButtonDownStaticSeq, WmLButtonUpStaticSeq, WmSetFontStaticSeq, WmSetTextGroupSeq }, { BS_USERBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON, WmSetFocusButtonSeq, WmKillFocusButtonSeq, WmSetStyleUserSeq, WmSetStateUserSeq, WmClearStateButtonSeq, WmSetCheckIgnoredSeq, WmLButtonDownSeq, WmLButtonUpSeq, WmSetFontButtonSeq, WmSetTextButtonSeq }, { BS_AUTORADIOBUTTON, DLGC_BUTTON | DLGC_RADIOBUTTON, WmSetFocusStaticSeq, WmKillFocusStaticSeq, WmSetStyleStaticSeq, WmSetStateStaticSeq, WmSetStateStaticSeq, WmSetCheckStaticSeq, NULL /* avoid infinite loop */, WmLButtonUpBrokenSeq, WmSetFontStaticSeq, WmSetTextStaticSeq }, { BS_OWNERDRAW, DLGC_BUTTON, WmSetFocusOwnerdrawSeq, WmKillFocusOwnerdrawSeq, WmSetStyleOwnerdrawSeq, WmSetStateOwnerdrawSeq, WmClearStateOwnerdrawSeq, WmSetCheckIgnoredSeq, WmLButtonDownSeq, WmLButtonUpSeq, WmSetFontButtonSeq, WmSetTextButtonSeq }, }; LOGFONTA logfont = { 0 }; HFONT zfont, hfont2; unsigned int i; HWND hwnd, parent; DWORD dlg_code;
/* selection with VK_SPACE should capture button window */ hwnd = CreateWindowExA(0, "button", "test", BS_CHECKBOX | WS_VISIBLE | WS_POPUP, 0, 0, 50, 14, 0, 0, 0, NULL); ok(hwnd != 0, "Failed to create button window\n"); ReleaseCapture(); SetFocus(hwnd); SendMessageA(hwnd, WM_KEYDOWN, VK_SPACE, 0); ok(GetCapture() == hwnd, "Should be captured on VK_SPACE WM_KEYDOWN\n"); SendMessageA(hwnd, WM_KEYUP, VK_SPACE, 0); DestroyWindow(hwnd);
subclass_button();
parent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 200, 200, 0, 0, 0, NULL); ok(parent != 0, "Failed to create parent window\n");
memset(&logfont, 0, sizeof(logfont)); logfont.lfHeight = -12; logfont.lfWeight = FW_NORMAL; strcpy(logfont.lfFaceName, "Tahoma");
hfont2 = CreateFontIndirectA(&logfont); ok(hfont2 != NULL, "Failed to create Tahoma font\n");
for (i = 0; i < ARRAY_SIZE(button); i++) { MSG msg; DWORD style, state; HFONT prevfont; char desc[64]; HDC hdc;
trace("button style %08x\n", button[i].style);
hwnd = CreateWindowExA(0, "my_button_class", "test", button[i].style | WS_CHILD | BS_NOTIFY, 0, 0, 50, 14, parent, (HMENU)ID_BUTTON, 0, NULL); ok(hwnd != 0, "Failed to create button window\n");
style = GetWindowLongA(hwnd, GWL_STYLE); style &= ~(WS_CHILD | BS_NOTIFY); /* XP turns a BS_USERBUTTON into BS_PUSHBUTTON */ if (button[i].style == BS_USERBUTTON) ok(style == BS_PUSHBUTTON, "expected style BS_PUSHBUTTON got %x\n", style); else ok(style == button[i].style, "expected style %x got %x\n", button[i].style, style);
dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0); ok(dlg_code == button[i].dlg_code, "%u: wrong dlg_code %08x\n", i, dlg_code);
ShowWindow(hwnd, SW_SHOW); UpdateWindow(hwnd); SetFocus(0); flush_events(); SetFocus(0); flush_sequence();
log_all_parent_messages++;
ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus()); SetFocus(hwnd); SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(button[i].setfocus, "SetFocus(hwnd) on a button", FALSE);
SetFocus(0); SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(button[i].killfocus, "SetFocus(0) on a button", FALSE);
ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
SendMessageA(hwnd, BM_SETSTYLE, button[i].style | BS_BOTTOM, TRUE); SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(button[i].setstyle, "BM_SETSTYLE on a button", FALSE);
style = GetWindowLongA(hwnd, GWL_STYLE); style &= ~(WS_VISIBLE | WS_CHILD | BS_NOTIFY); /* XP doesn't turn a BS_USERBUTTON into BS_PUSHBUTTON here! */ ok(style == button[i].style, "expected style %04x got %04x\n", button[i].style, style);
state = SendMessageA(hwnd, BM_GETSTATE, 0, 0); ok(state == 0, "expected state 0, got %04x\n", state);
flush_sequence();
SendMessageA(hwnd, BM_SETSTATE, TRUE, 0); SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(button[i].setstate, "BM_SETSTATE/TRUE on a button", FALSE);
state = SendMessageA(hwnd, BM_GETSTATE, 0, 0); ok(state == 0x0004, "expected state 0x0004, got %04x\n", state);
style = GetWindowLongA(hwnd, GWL_STYLE); style &= ~(WS_CHILD | BS_NOTIFY | WS_VISIBLE); ok(style == button[i].style, "expected style %04x got %04x\n", button[i].style, style);
flush_sequence();
SendMessageA(hwnd, BM_SETSTATE, FALSE, 0); SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(button[i].clearstate, "BM_SETSTATE/FALSE on a button", FALSE);
state = SendMessageA(hwnd, BM_GETSTATE, 0, 0); ok(state == 0, "expected state 0, got %04x\n", state);
style = GetWindowLongA(hwnd, GWL_STYLE); style &= ~(WS_CHILD | BS_NOTIFY | WS_VISIBLE); ok(style == button[i].style, "expected style %04x got %04x\n", button[i].style, style);
state = SendMessageA(hwnd, BM_GETCHECK, 0, 0); ok(state == BST_UNCHECKED, "expected BST_UNCHECKED, got %04x\n", state);
flush_sequence();
SendMessageA(hwnd, BM_SETCHECK, BST_UNCHECKED, 0); SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(WmSetCheckIgnoredSeq, "BM_SETCHECK on a button", FALSE);
state = SendMessageA(hwnd, BM_GETCHECK, 0, 0); ok(state == BST_UNCHECKED, "expected BST_UNCHECKED, got %04x\n", state);
style = GetWindowLongA(hwnd, GWL_STYLE); style &= ~(WS_CHILD | BS_NOTIFY | WS_VISIBLE); ok(style == button[i].style, "expected style %04x got %04x\n", button[i].style, style);
flush_sequence();
SendMessageA(hwnd, BM_SETCHECK, BST_CHECKED, 0); SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(button[i].setcheck, "BM_SETCHECK on a button", FALSE);
SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"Text 1"); sprintf(desc, "button[%i]: WM_SETTEXT on a visible button", i); ok_sequence(button[i].settext, desc, FALSE);
ShowWindow(hwnd, SW_HIDE); flush_events(); flush_sequence();
SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"Text 2"); sprintf(desc, "button[%i]: WM_SETTEXT on an invisible button", i); ok_sequence(WmSetTextInvisibleSeq, desc, FALSE);
ShowWindow(hwnd, SW_SHOW); ShowWindow(parent, SW_HIDE); flush_events(); flush_sequence();
SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"Text 3"); sprintf(desc, "button[%i]: WM_SETTEXT on an invisible button", i); ok_sequence(WmSetTextInvisibleSeq, desc, FALSE);
ShowWindow(parent, SW_SHOW); flush_events();
state = SendMessageA(hwnd, BM_GETCHECK, 0, 0); if (button[i].style == BS_PUSHBUTTON || button[i].style == BS_DEFPUSHBUTTON || button[i].style == BS_GROUPBOX || button[i].style == BS_USERBUTTON || button[i].style == BS_OWNERDRAW) ok(state == BST_UNCHECKED, "expected check 0, got %04x\n", state); else ok(state == BST_CHECKED, "expected check 1, got %04x\n", state);
style = GetWindowLongA(hwnd, GWL_STYLE); style &= ~(WS_CHILD | BS_NOTIFY | WS_VISIBLE); if (button[i].style == BS_RADIOBUTTON || button[i].style == BS_AUTORADIOBUTTON) ok(style == (button[i].style | WS_TABSTOP), "expected style %04x | WS_TABSTOP got %04x\n", button[i].style, style); else ok(style == button[i].style, "expected style %04x got %04x\n", button[i].style, style);
log_all_parent_messages--;
DestroyWindow(hwnd);
hwnd = CreateWindowExA(0, "my_button_class", "test", button[i].style | WS_POPUP | WS_VISIBLE, 0, 0, 50, 14, 0, 0, 0, NULL); ok(hwnd != 0, "Failed to create button window\n");
SetForegroundWindow(hwnd); flush_events();
SetActiveWindow(hwnd); SetFocus(0); flush_sequence();
if (button[i].lbuttondown) { SendMessageA(hwnd, WM_LBUTTONDOWN, 0, 0); sprintf(desc, "button[%i]: WM_LBUTTONDOWN on a button", i); ok_sequence(button[i].lbuttondown, desc, FALSE); }
SendMessageA(hwnd, WM_LBUTTONUP, 0, 0); sprintf(desc, "button[%i]: WM_LBUTTONUP on a button", i); ok_sequence(button[i].lbuttonup, desc, FALSE);
flush_sequence(); zfont = GetStockObject(DEFAULT_GUI_FONT); SendMessageA(hwnd, WM_SETFONT, (WPARAM)zfont, TRUE); UpdateWindow(hwnd); sprintf(desc, "button[%i]: WM_SETFONT on a button", i); ok_sequence(button[i].setfont, desc, FALSE);
/* Test that original font is not selected back after painting */ hdc = CreateCompatibleDC(0);
prevfont = SelectObject(hdc, hfont2); ok(prevfont == GetStockObject(SYSTEM_FONT), "Unexpected default font\n"); SendMessageA(hwnd, WM_PRINTCLIENT, (WPARAM)hdc, 0); ok(hfont2 != GetCurrentObject(hdc, OBJ_FONT), "button[%u]: unexpected font selected after WM_PRINTCLIENT\n", i); SelectObject(hdc, prevfont);
prevfont = SelectObject(hdc, hfont2); ok(prevfont == GetStockObject(SYSTEM_FONT), "Unexpected default font\n"); SendMessageA(hwnd, WM_PAINT, (WPARAM)hdc, 0); ok(hfont2 != GetCurrentObject(hdc, OBJ_FONT), "button[%u]: unexpected font selected after WM_PAINT\n", i); SelectObject(hdc, prevfont);
DeleteDC(hdc);
DestroyWindow(hwnd); }
DeleteObject(hfont2); DestroyWindow(parent);
/* Test if WM_LBUTTONDOWN and WM_LBUTTONUP to a disabled button leads to a WM_COMMAND for the parent */
parent = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 200, 200, 0, 0, 0, NULL); ok (hwnd != 0, "Failed to create overlapped window\n");
hwnd = CreateWindowExA(0, "my_button_class", "test", BS_DEFPUSHBUTTON | WS_VISIBLE | WS_CHILD, 0, 0, 50, 14, parent, 0, 0, NULL);
EnableWindow(hwnd, FALSE); flush_sequence(); SendMessageA(hwnd, WM_LBUTTONDOWN, MK_LBUTTON, 0); SendMessageA(hwnd, WM_LBUTTONUP, 0, 0); ok_sequence(WmDisableButtonSeq, "Mouseclick on a disabled button", FALSE);
DestroyWindow(hwnd); DestroyWindow(parent);}
static void test_button_bm_get_set_image(void){ HWND hwnd; HDC hdc; HBITMAP hbmp1x1; HBITMAP hbmp2x2; HBITMAP hmask2x2; ICONINFO icon_info2x2; HICON hicon2x2; HBITMAP hbmp; HICON hicon; ICONINFO icon_info; BITMAP bm; DWORD default_style = BS_PUSHBUTTON | WS_TABSTOP | WS_POPUP | WS_VISIBLE; LRESULT ret;
hdc = GetDC(0); hbmp1x1 = CreateCompatibleBitmap(hdc, 1, 1); hbmp2x2 = CreateCompatibleBitmap(hdc, 2, 2); ZeroMemory(&bm, sizeof(bm)); ok(GetObjectW(hbmp1x1, sizeof(bm), &bm), "Expect GetObjectW() success\n"); ok(bm.bmWidth == 1 && bm.bmHeight == 1, "Expect bitmap size: %d,%d, got: %d,%d\n", 1, 1, bm.bmWidth, bm.bmHeight); ZeroMemory(&bm, sizeof(bm)); ok(GetObjectW(hbmp2x2, sizeof(bm), &bm), "Expect GetObjectW() success\n"); ok(bm.bmWidth == 2 && bm.bmHeight == 2, "Expect bitmap size: %d,%d, got: %d,%d\n", 2, 2, bm.bmWidth, bm.bmHeight);
hmask2x2 = CreateCompatibleBitmap(hdc, 2, 2); ZeroMemory(&icon_info2x2, sizeof(icon_info2x2)); icon_info2x2.fIcon = TRUE; icon_info2x2.hbmMask = hmask2x2; icon_info2x2.hbmColor = hbmp2x2; hicon2x2 = CreateIconIndirect(&icon_info2x2);
ZeroMemory(&icon_info, sizeof(icon_info)); ok(GetIconInfo(hicon2x2, &icon_info), "Expect GetIconInfo() success\n"); ZeroMemory(&bm, sizeof(bm)); ok(GetObjectW(icon_info.hbmColor, sizeof(bm), &bm), "Expect GetObjectW() success\n"); ok(bm.bmWidth == 2 && bm.bmHeight == 2, "Expect bitmap size: %d,%d, got: %d,%d\n", 2, 2, bm.bmWidth, bm.bmHeight); DeleteObject(icon_info.hbmColor); DeleteObject(icon_info.hbmMask);
/* Set bitmap with BS_BITMAP */ hwnd = CreateWindowA("Button", "test", default_style | BS_BITMAP, 0, 0, 100, 100, 0, 0, 0, 0); ok(hwnd != NULL, "Expect hwnd not NULL\n"); SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hbmp1x1); hbmp = (HBITMAP)SendMessageA(hwnd, BM_GETIMAGE, (WPARAM)IMAGE_BITMAP, 0); ok(hbmp != 0, "Expect hbmp not 0\n"); ZeroMemory(&bm, sizeof(bm)); ok(GetObjectW(hbmp, sizeof(bm), &bm), "Expect GetObjectW() success\n"); ok(bm.bmWidth == 1 && bm.bmHeight == 1, "Expect bitmap size: %d,%d, got: %d,%d\n", 1, 1, bm.bmWidth, bm.bmHeight); DestroyWindow(hwnd);
/* Set bitmap without BS_BITMAP */ hwnd = CreateWindowA("Button", "test", default_style, 0, 0, 100, 100, 0, 0, 0, 0); ok(hwnd != NULL, "Expect hwnd not NULL\n"); ret = SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hbmp1x1); ok(ret == 0, "Expect ret to be 0\n"); hbmp = (HBITMAP)SendMessageA(hwnd, BM_GETIMAGE, (WPARAM)IMAGE_BITMAP, 0); ok(hbmp == NULL, "Expect hbmp to be NULL\n"); DestroyWindow(hwnd);
/* Set icon with BS_ICON */ hwnd = CreateWindowA("Button", "test", default_style | BS_ICON, 0, 0, 100, 100, 0, 0, 0, 0); ok(hwnd != NULL, "Expect hwnd not NULL\n"); SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hicon2x2); hicon = (HICON)SendMessageA(hwnd, BM_GETIMAGE, (WPARAM)IMAGE_ICON, 0); ok(hicon != NULL, "Expect hicon not NULL\n"); ZeroMemory(&icon_info, sizeof(icon_info)); ok(GetIconInfo(hicon, &icon_info), "Expect GetIconInfo() success\n"); ZeroMemory(&bm, sizeof(bm)); ok(GetObjectW(icon_info.hbmColor, sizeof(bm), &bm), "Expect GetObjectW() success\n"); ok(bm.bmWidth == 2 && bm.bmHeight == 2, "Expect bitmap size: %d,%d, got: %d,%d\n", 2, 2, bm.bmWidth, bm.bmHeight); DeleteObject(icon_info.hbmColor); DeleteObject(icon_info.hbmMask); DestroyWindow(hwnd);
/* Set icon without BS_ICON */ hwnd = CreateWindowA("Button", "test", default_style, 0, 0, 100, 100, 0, 0, 0, 0); ok(hwnd != NULL, "Expect hwnd not NULL\n"); ret = SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hicon2x2); ok(ret == 0, "Expect ret to be 0\n"); hicon = (HICON)SendMessageA(hwnd, BM_GETIMAGE, (WPARAM)IMAGE_ICON, 0); ok(hicon == NULL, "Expect hicon to be NULL\n"); DestroyWindow(hwnd);
/* Set icon with BS_BITMAP */ hwnd = CreateWindowA("Button", "test", default_style | BS_BITMAP, 0, 0, 100, 100, 0, 0, 0, 0); ok(hwnd != NULL, "Expect hwnd to be not NULL\n"); ret = SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hicon2x2); ok(ret == 0, "Expect ret to be 0\n"); hicon = (HICON)SendMessageA(hwnd, BM_GETIMAGE, (WPARAM)IMAGE_ICON, 0); ok(hicon == NULL, "Expect hicon to be NULL\n"); DestroyWindow(hwnd);
/* Set bitmap with BS_ICON */ hwnd = CreateWindowA("Button", "test", default_style | BS_ICON, 0, 0, 100, 100, 0, 0, 0, 0); ok(hwnd != NULL, "Expect hwnd to be not NULL\n"); ret = SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hbmp1x1); ok(ret == 0, "Expect ret to be 0\n"); hbmp = (HBITMAP)SendMessageA(hwnd, BM_GETIMAGE, (WPARAM)IMAGE_BITMAP, 0); ok(hbmp == NULL, "Expect hbmp to be NULL\n"); DestroyWindow(hwnd);
DestroyIcon(hicon2x2); DeleteObject(hmask2x2); DeleteObject(hbmp2x2); DeleteObject(hbmp1x1); ReleaseDC(0, hdc);}
#define ID_RADIO1 501#define ID_RADIO2 502#define ID_RADIO3 503#define ID_TEXT 504
static const struct message auto_radio_button_BM_CLICK[] ={ { BM_CLICK, sent|wparam|lparam, 0, 0 }, { WM_LBUTTONDOWN, sent|wparam|lparam|defwinproc, 0, 0 }, { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, { BM_SETSTATE, sent|wparam|lparam|defwinproc, BST_CHECKED, ID_RADIO2 }, { WM_CTLCOLORSTATIC, sent|parent }, { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_LBUTTONUP, sent|wparam|lparam|defwinproc, 0, 0 }, { BM_SETSTATE, sent|wparam|lparam|defwinproc, BST_UNCHECKED, ID_RADIO2 }, { WM_CTLCOLORSTATIC, sent|parent }, { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_GETDLGCODE, sent|wparam|lparam|defwinproc, ID_RADIO2, 0 }, { BM_SETCHECK, sent|wparam|lparam|defwinproc, BST_CHECKED, ID_RADIO2 }, { WM_GETDLGCODE, sent|wparam|lparam|defwinproc, ID_RADIO1, 0 }, { BM_SETCHECK, sent|wparam|lparam|defwinproc, 0, ID_RADIO1 }, { WM_CTLCOLORSTATIC, sent|parent }, { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_GETDLGCODE, sent|wparam|lparam|defwinproc, ID_RADIO3, 0 }, { BM_SETCHECK, sent|wparam|lparam|defwinproc, 0, ID_RADIO3 }, { WM_CTLCOLORSTATIC, sent|parent }, { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_GETDLGCODE, sent|wparam|lparam|defwinproc, ID_TEXT, 0 }, { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 }, { WM_CAPTURECHANGED, sent|wparam|lparam|defwinproc, 0, 0 }, { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_RADIO2, BN_CLICKED) }, { WM_NCHITTEST, sent|optional, 0, 0 }, /* FIXME: Wine doesn't send it */ { WM_SETCURSOR, sent|optional, 0, 0 }, /* FIXME: Wine doesn't send it */ { WM_MOUSEMOVE, sent|optional, 0, 0 }, /* FIXME: Wine doesn't send it */ { 0 }};
static const struct message auto_radio_button_VK_UP_child[] ={ { WM_KEYDOWN, sent|wparam|lparam, VK_UP, 0 }, { WM_KEYUP, sent|wparam|lparam, VK_UP, 0 }, { 0 }};
static const struct message auto_radio_button_VK_UP_parent[] ={ { WM_KEYDOWN, sent|wparam|lparam|parent, VK_UP, 0 }, { WM_KEYUP, sent|wparam|lparam|parent, VK_UP, 0 }, { 0 }};
static const struct message auto_radio_button_VK_UP_dialog[] ={ { WM_GETDLGCODE, sent|parent, 0, 0 },
/* optional trailer seen on some windows setups */ { WM_CHANGEUISTATE, sent|optional }, { WM_UPDATEUISTATE, sent|optional }, { WM_UPDATEUISTATE, sent|optional }, { WM_UPDATEUISTATE, sent|optional }, { WM_UPDATEUISTATE, sent|optional }, { WM_UPDATEUISTATE, sent|optional }, { WM_UPDATEUISTATE, sent|optional }, { WM_UPDATEUISTATE, sent|optional }, { WM_UPDATEUISTATE, sent|optional }, { WM_UPDATEUISTATE, sent|optional }, { WM_UPDATEUISTATE, sent|optional }, { WM_UPDATEUISTATE, sent|optional }, { WM_UPDATEUISTATE, sent|optional }, { WM_UPDATEUISTATE, sent|optional }, { WM_UPDATEUISTATE, sent|optional }, { WM_UPDATEUISTATE, sent|optional }, { WM_UPDATEUISTATE, sent|optional }, { WM_UPDATEUISTATE, sent|optional }, { WM_UPDATEUISTATE, sent|optional }, { WM_CTLCOLORSTATIC, sent|parent|optional }, { WM_CTLCOLORSTATIC, sent|parent|optional }, { WM_CTLCOLORSTATIC, sent|parent|optional }, { WM_UPDATEUISTATE, sent|optional }, { WM_CTLCOLORSTATIC, sent|parent|optional }, { WM_CTLCOLORSTATIC, sent|parent|optional }, { WM_UPDATEUISTATE, sent|optional }, { WM_CTLCOLORBTN, sent|parent|optional }, { WM_CTLCOLORBTN, sent|parent|optional }, { WM_UPDATEUISTATE, sent|optional }, { WM_CTLCOLORSTATIC, sent|parent|optional }, { WM_CTLCOLORSTATIC, sent|parent|optional }, { 0 }};
static const struct message auto_radio_button_VK_DOWN_dialog[] ={ { WM_GETDLGCODE, sent|parent, 0, 0 }, { WM_GETDLGCODE, sent|wparam|lparam, ID_RADIO1, MAKELPARAM(WM_KEYDOWN, VK_DOWN) }, { WM_GETDLGCODE, sent|wparam|lparam, ID_RADIO1, 0 }, { HCBT_SETFOCUS, hook }, { WM_KILLFOCUS, sent, 0, 0 }, { WM_CTLCOLORSTATIC, sent|parent }, { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_RADIO3, BN_KILLFOCUS) }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent, 0, 0 }, { WM_CTLCOLORSTATIC, sent|parent }, { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_RADIO1, BN_SETFOCUS) }, { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_RADIO1, BN_CLICKED) }, { WM_GETDLGCODE, sent|wparam|lparam, ID_RADIO1, 0 }, { WM_GETDLGCODE, sent|parent, 0, 0 }, { DM_GETDEFID, sent|parent, 0, 0 }, { BM_GETCHECK, sent|wparam|lparam, 0, ID_RADIO1 }, { BM_CLICK, sent|wparam|lparam, 1, 0 }, { WM_LBUTTONDOWN, sent|wparam|lparam|defwinproc, 0, 0 }, { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, { BM_SETSTATE, sent|wparam|lparam|defwinproc, BST_CHECKED, ID_RADIO1 }, { WM_CTLCOLORSTATIC, sent|parent }, { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_LBUTTONUP, sent|wparam|lparam|defwinproc, 0, 0 }, { BM_SETSTATE, sent|wparam|lparam|defwinproc, BST_UNCHECKED, ID_RADIO1 }, { WM_CTLCOLORSTATIC, sent|parent }, { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_GETDLGCODE, sent|wparam|lparam|defwinproc, ID_RADIO1, 0 }, { BM_SETCHECK, sent|wparam|lparam|defwinproc, BST_CHECKED, ID_RADIO1 }, { WM_CTLCOLORSTATIC, sent|parent }, { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_GETDLGCODE, sent|wparam|lparam|defwinproc, ID_RADIO3, 0 }, { BM_SETCHECK, sent|wparam|lparam|defwinproc, BST_UNCHECKED, ID_RADIO3 }, { WM_CTLCOLORSTATIC, sent|parent }, { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_GETDLGCODE, sent|wparam|lparam|defwinproc, ID_TEXT, 0 }, { WM_GETDLGCODE, sent|wparam|lparam|defwinproc, ID_RADIO2, 0 }, { BM_SETCHECK, sent|wparam|lparam|defwinproc, BST_UNCHECKED, ID_RADIO2 }, { WM_CTLCOLORSTATIC, sent|parent }, { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 }, { WM_CAPTURECHANGED, sent|wparam|lparam|defwinproc, 0, 0 }, { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_RADIO1, BN_CLICKED) }, { WM_NCHITTEST, sent|optional, 0, 0 }, /* FIXME: Wine doesn't send it */ { WM_SETCURSOR, sent|optional, 0, 0 }, /* FIXME: Wine doesn't send it */ { WM_MOUSEMOVE, sent|optional, 0, 0 }, /* FIXME: Wine doesn't send it */ { WM_PAINT, sent }, { WM_CTLCOLORSTATIC, sent|parent }, { 0 }};
static const struct message auto_radio_button_VK_DOWN_radio3[] ={ { BM_GETCHECK, sent|wparam|lparam, 0, ID_RADIO1 }, { BM_GETCHECK, sent|wparam|lparam, 0, ID_RADIO2 }, { BM_GETCHECK, sent|wparam|lparam, 0, ID_RADIO3 }, { WM_GETDLGCODE, sent|parent, 0, 0 }, { WM_GETDLGCODE, sent|wparam|lparam, ID_RADIO1, MAKELPARAM(WM_KEYDOWN, VK_DOWN) }, { WM_GETDLGCODE, sent|wparam|lparam, ID_RADIO1, 0 }, { WM_GETDLGCODE, sent|wparam|lparam, ID_RADIO1, 0 }, { WM_GETDLGCODE, sent|wparam|lparam|parent, 0, 0 }, { WM_USER, sent|parent, 0, 0 }, { BM_GETCHECK, sent|wparam|lparam, 0, ID_RADIO1 }, { 0 }};
static const struct message auto_radio_button_VK_UP_radio1[] ={ { WM_GETDLGCODE, sent|parent, 0, 0 }, { 0 }};
static INT_PTR WINAPI radio_test_dlg_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp){ ParentMsgCheckProcA(hwnd, msg, wp, lp); return 1;}
static void test_autoradio_BM_CLICK(void){ HWND parent, radio1, radio2, radio3; RECT rc; MSG msg; DWORD ret;
subclass_button();
parent = CreateDialogParamA(0, "AUTORADIO_TEST_DIALOG_1", 0, radio_test_dlg_proc, 0); ok(parent != 0, "failed to create parent window\n");
radio1 = GetDlgItem(parent, ID_RADIO1); radio2 = GetDlgItem(parent, ID_RADIO2); radio3 = GetDlgItem(parent, ID_RADIO3);
/* this avoids focus messages in the generated sequence */ SetFocus(radio2);
flush_events(); flush_sequence();
ret = SendMessageA(radio1, BM_GETCHECK, 0, 0); ok(ret == BST_UNCHECKED, "got %08x\n", ret); ret = SendMessageA(radio2, BM_GETCHECK, 0, 0); ok(ret == BST_UNCHECKED, "got %08x\n", ret); ret = SendMessageA(radio3, BM_GETCHECK, 0, 0); ok(ret == BST_UNCHECKED, "got %08x\n", ret);
SendMessageA(radio1, BM_SETCHECK, BST_CHECKED, 0);
ret = SendMessageA(radio1, BM_GETCHECK, 0, 0); ok(ret == BST_CHECKED, "got %08x\n", ret); ret = SendMessageA(radio2, BM_GETCHECK, 0, 0); ok(ret == BST_UNCHECKED, "got %08x\n", ret); ret = SendMessageA(radio3, BM_GETCHECK, 0, 0); ok(ret == BST_UNCHECKED, "got %08x\n", ret);
SendMessageA(radio2, BM_SETCHECK, BST_CHECKED, 0);
ret = SendMessageA(radio1, BM_GETCHECK, 0, 0); ok(ret == BST_CHECKED, "got %08x\n", ret); ret = SendMessageA(radio2, BM_GETCHECK, 0, 0); ok(ret == BST_CHECKED, "got %08x\n", ret); ret = SendMessageA(radio3, BM_GETCHECK, 0, 0); ok(ret == BST_UNCHECKED, "got %08x\n", ret);
SendMessageA(radio3, BM_SETCHECK, BST_CHECKED, 0);
ret = SendMessageA(radio1, BM_GETCHECK, 0, 0); ok(ret == BST_CHECKED, "got %08x\n", ret); ret = SendMessageA(radio2, BM_GETCHECK, 0, 0); ok(ret == BST_CHECKED, "got %08x\n", ret); ret = SendMessageA(radio3, BM_GETCHECK, 0, 0); ok(ret == BST_CHECKED, "got %08x\n", ret);
GetWindowRect(radio2, &rc); SetCursorPos(rc.left+1, rc.top+1);
flush_events(); flush_sequence();
log_all_parent_messages++;
SendMessageA(radio2, BM_CLICK, 0, 0); while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(auto_radio_button_BM_CLICK, "BM_CLICK on auto-radio button", FALSE);
log_all_parent_messages--;
ret = SendMessageA(radio1, BM_GETCHECK, 0, 0); ok(ret == BST_UNCHECKED, "got %08x\n", ret); ret = SendMessageA(radio2, BM_GETCHECK, 0, 0); ok(ret == BST_CHECKED, "got %08x\n", ret); ret = SendMessageA(radio3, BM_GETCHECK, 0, 0); ok(ret == BST_UNCHECKED, "got %08x\n", ret);
DestroyWindow(parent);}
#define test_radio(r1, s1, r2, s2, r3, s3) test_radio_dbg(r1, s1, r2, s2, r3, s3, __LINE__)static void test_radio_dbg(HWND radio1, int state1, HWND radio2, int state2, HWND radio3, int state3, int line){ DWORD ret;
ret = SendMessageA(radio1, BM_GETCHECK, 0, 0); ok_(__FILE__,line)(ret == state1 ? BST_CHECKED : BST_UNCHECKED, "got %08x\n", ret); ret = SendMessageA(radio2, BM_GETCHECK, 0, 0); ok_(__FILE__,line)(ret == state2 ? BST_CHECKED : BST_UNCHECKED, "got %08x\n", ret); ret = SendMessageA(radio3, BM_GETCHECK, 0, 0); ok_(__FILE__,line)(ret == state3 ? BST_CHECKED : BST_UNCHECKED, "got %08x\n", ret);}
static void set_radio(HWND radio1, int state1, HWND radio2, int state2, HWND radio3, int state3){ SendMessageA(radio1, BM_SETCHECK, state1 ? BST_CHECKED : BST_UNCHECKED, 0); SendMessageA(radio2, BM_SETCHECK, state2 ? BST_CHECKED : BST_UNCHECKED, 0); SendMessageA(radio3, BM_SETCHECK, state3 ? BST_CHECKED : BST_UNCHECKED, 0);}
static void test_autoradio_kbd_move(void){ HWND parent, radio1, radio2, radio3, hwnd; RECT rc; MSG msg; DWORD ret;
subclass_button();
parent = CreateDialogParamA(0, "AUTORADIO_TEST_DIALOG_2", 0, radio_test_dlg_proc, 0); ok(parent != 0, "failed to create parent window\n");
radio1 = GetDlgItem(parent, ID_RADIO1); radio2 = GetDlgItem(parent, ID_RADIO2); radio3 = GetDlgItem(parent, ID_RADIO3);
flush_events(); flush_sequence();
test_radio(radio1, 0, radio2, 0, radio3, 0); set_radio(radio1, 1, radio2, 1, radio3, 1); test_radio(radio1, 1, radio2, 1, radio3, 1);
SetFocus(radio3);
flush_events(); flush_sequence();
log_all_parent_messages++;
SendMessageA(radio3, WM_KEYDOWN, VK_UP, 0); SendMessageA(radio3, WM_KEYUP, VK_UP, 0); while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(auto_radio_button_VK_UP_child, "press/release VK_UP on auto-radio button", FALSE);
test_radio(radio1, 1, radio2, 1, radio3, 1);
flush_events(); flush_sequence();
DefDlgProcA(parent, WM_KEYDOWN, VK_UP, 0); DefDlgProcA(parent, WM_KEYUP, VK_UP, 0); while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(auto_radio_button_VK_UP_parent, "press/release VK_UP on dialog", FALSE);
test_radio(radio1, 1, radio2, 1, radio3, 1);
SetFocus(radio3); GetWindowRect(radio3, &rc);
flush_events(); flush_sequence();
msg.hwnd = parent; msg.message = WM_KEYDOWN; msg.wParam = VK_UP; msg.lParam = 0; msg.pt.x = rc.left + 1; msg.pt.y = rc.top + 1; ret = IsDialogMessageA(parent, &msg); ok(ret, "IsDialogMessage should return TRUE\n"); while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);if (0) /* actual message sequence is different on every run in some Windows setups */ ok_sequence(auto_radio_button_VK_UP_dialog, "IsDialogMessage(VK_UP) #1", FALSE); /* what really matters is that nothing has changed */ test_radio(radio1, 1, radio2, 1, radio3, 1);
set_radio(radio1, 0, radio2, 1, radio3, 1); test_radio(radio1, 0, radio2, 1, radio3, 1);
flush_events(); flush_sequence();
ret = IsDialogMessageA(parent, &msg); ok(ret, "IsDialogMessage should return TRUE\n"); while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);if (0) /* actual message sequence is different on every run in some Windows setups */ ok_sequence(auto_radio_button_VK_UP_dialog, "IsDialogMessage(VK_UP) #2", FALSE); /* what really matters is that nothing has changed */ test_radio(radio1, 0, radio2, 1, radio3, 1);
/* switch from radio3 ro radio1 */ SetFocus(radio3); GetWindowRect(radio3, &rc);
flush_events(); flush_sequence();
msg.hwnd = parent; msg.message = WM_KEYDOWN; msg.wParam = VK_DOWN; msg.lParam = 0; msg.pt.x = rc.left + 1; msg.pt.y = rc.top + 1; ret = IsDialogMessageA(parent, &msg); ok(ret, "IsDialogMessage should return TRUE\n"); while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(auto_radio_button_VK_DOWN_dialog, "IsDialogMessage(VK_DOWN)", TRUE);
test_radio(radio1, 1, radio2, 0, radio3, 0);
hwnd = GetFocus(); ok(hwnd == radio1, "focus should be on radio1, not on %p\n", hwnd); GetWindowRect(radio1, &rc);
msg.hwnd = parent; msg.message = WM_KEYDOWN; msg.wParam = VK_DOWN; msg.lParam = 0; msg.pt.x = rc.left + 1; msg.pt.y = rc.top + 1; ret = IsDialogMessageA(parent, &msg); ok(ret, "IsDialogMessage should return TRUE\n"); while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(auto_radio_button_VK_DOWN_radio3, "down to radio3", TRUE);
test_radio(radio1, 1, radio2, 0, radio3, 0);
hwnd = GetFocus(); ok(hwnd == radio1, "focus should be on radio1, not on %p\n", hwnd);
flush_events(); flush_sequence();
msg.hwnd = parent; msg.message = WM_KEYDOWN; msg.wParam = VK_UP; msg.lParam = 0; msg.pt.x = rc.left + 1; msg.pt.y = rc.top + 1; ret = IsDialogMessageA(parent, &msg); ok(ret, "IsDialogMessage should return TRUE\n"); while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(auto_radio_button_VK_UP_radio1, "up to radio1", TRUE);
test_radio(radio1, 1, radio2, 0, radio3, 0);
hwnd = GetFocus(); ok(hwnd == radio1, "focus should be on radio1, not on %p\n", hwnd);
flush_events(); flush_sequence();
msg.hwnd = parent; msg.message = WM_KEYDOWN; msg.wParam = VK_UP; msg.lParam = 0; msg.pt.x = rc.left + 1; msg.pt.y = rc.top + 1; ret = IsDialogMessageA(parent, &msg); ok(ret, "IsDialogMessage should return TRUE\n"); while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);if (0) /* actual message sequence is different on every run in some Windows setups */ ok_sequence(auto_radio_button_VK_UP_dialog, "IsDialogMessage(VK_UP) #3", FALSE); /* what really matters is that nothing has changed */ test_radio(radio1, 1, radio2, 0, radio3, 0);
log_all_parent_messages--;
DestroyWindow(parent);}
/****************** static message test *************************/static const struct message WmSetFontStaticSeq2[] ={ { WM_SETFONT, sent }, { WM_PAINT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent|defwinproc|optional }, { WM_CTLCOLORSTATIC, sent|defwinproc|optional }, { 0 }};
static WNDPROC old_static_proc;
static LRESULT CALLBACK static_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ static LONG defwndproc_counter = 0; LRESULT ret; struct recvd_message msg;
if (ignore_message( message )) return 0;
msg.hwnd = hwnd; msg.message = message; msg.flags = sent|wparam|lparam; if (defwndproc_counter) msg.flags |= defwinproc; msg.wParam = wParam; msg.lParam = lParam; msg.descr = "static"; add_message(&msg);
defwndproc_counter++; ret = CallWindowProcA(old_static_proc, hwnd, message, wParam, lParam); defwndproc_counter--;
return ret;}
static void subclass_static(void){ WNDCLASSA cls;
if (!GetClassInfoA(0, "static", &cls)) assert(0);
old_static_proc = cls.lpfnWndProc;
cls.hInstance = GetModuleHandleA(NULL); cls.lpfnWndProc = static_hook_proc; cls.lpszClassName = "my_static_class"; UnregisterClassA(cls.lpszClassName, cls.hInstance); if (!RegisterClassA(&cls)) assert(0);}
static void test_static_messages(void){ /* FIXME: make as comprehensive as the button message test */ static const struct { DWORD style; DWORD dlg_code; const struct message *setfont; } static_ctrl[] = { { SS_LEFT, DLGC_STATIC, WmSetFontStaticSeq2 } }; unsigned int i; HWND hwnd; DWORD dlg_code;
subclass_static();
for (i = 0; i < ARRAY_SIZE(static_ctrl); i++) { hwnd = CreateWindowExA(0, "my_static_class", "test", static_ctrl[i].style | WS_POPUP, 0, 0, 50, 14, 0, 0, 0, NULL); ok(hwnd != 0, "Failed to create static window\n");
dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0); ok(dlg_code == static_ctrl[i].dlg_code, "%u: wrong dlg_code %08x\n", i, dlg_code);
ShowWindow(hwnd, SW_SHOW); UpdateWindow(hwnd); SetFocus(0); flush_sequence();
trace("static style %08x\n", static_ctrl[i].style); SendMessageA(hwnd, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), TRUE); ok_sequence(static_ctrl[i].setfont, "WM_SETFONT on a static", FALSE);
DestroyWindow(hwnd); }}
/****************** ComboBox message test *************************/#define ID_COMBOBOX 0x000f
static const struct message SetCurSelComboSeq[] ={ { CB_SETCURSEL, sent|wparam|lparam, 0, 0 }, { LB_SETCURSEL, sent|wparam|lparam, 0, 0 }, { LB_SETTOPINDEX, sent|wparam|lparam, 0, 0 }, { LB_GETCURSEL, sent|wparam|lparam, 0, 0 }, { LB_GETTEXTLEN, sent|wparam|lparam, 0, 0 }, { LB_GETTEXTLEN, sent|wparam|lparam|optional, 0, 0 }, /* TODO: it's sent on all Windows versions */ { LB_GETTEXT, sent|wparam, 0 }, { WM_CTLCOLOREDIT, sent|parent }, { LB_GETITEMDATA, sent|wparam|lparam, 0, 0 }, { WM_DRAWITEM, sent|wparam|lparam|parent, ID_COMBOBOX, 0x100010f3 }, { 0 }};
static const struct message SetCurSelComboSeq2[] ={ { CB_SETCURSEL, sent|wparam|lparam, 0, 0 }, { LB_SETCURSEL, sent|wparam|lparam, 0, 0 }, { LB_SETTOPINDEX, sent|wparam|lparam, 0, 0 }, { LB_GETCURSEL, sent|wparam|lparam, 0, 0 }, { LB_GETTEXTLEN, sent|wparam|lparam, 0, 0 }, { LB_GETTEXTLEN, sent|wparam|lparam|optional, 0, 0 }, /* TODO: it's sent on all Windows versions */ { LB_GETTEXT, sent|wparam, 0 }, { 0 }};
static const struct message SetCurSelComboSeq_edit[] ={ { CB_SETCURSEL, sent|wparam|lparam, 0, 0 }, { WM_SETTEXT, sent|wparam, 0 }, { EM_SETSEL, sent|wparam|lparam, 0, INT_MAX }, { 0 }};
static const struct message WmKeyDownComboSeq[] ={ { WM_KEYDOWN, sent|wparam|lparam, VK_DOWN, 0 }, { WM_COMMAND, sent|wparam|defwinproc, MAKEWPARAM(1000, LBN_SELCHANGE) }, { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_COMBOBOX, CBN_SELENDOK) }, { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_COMBOBOX, CBN_SELCHANGE) }, { WM_CTLCOLOREDIT, sent|parent }, { WM_KEYUP, sent|wparam|lparam, VK_DOWN, 0 }, { 0 }};
static const struct message WmSetPosComboSeq[] ={ { WM_WINDOWPOSCHANGING, sent }, { WM_NCCALCSIZE, sent|wparam, TRUE }, { WM_CHILDACTIVATE, sent }, { WM_WINDOWPOSCHANGED, sent }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, { WM_WINDOWPOSCHANGING, sent|defwinproc }, { WM_NCCALCSIZE, sent|defwinproc|wparam, TRUE }, { WM_WINDOWPOSCHANGED, sent|defwinproc }, { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, { 0 }};
static const struct message WMSetFocusComboBoxSeq[] ={ { WM_SETFOCUS, sent }, { WM_KILLFOCUS, sent|parent }, { WM_SETFOCUS, sent }, { WM_COMMAND, sent|defwinproc|wparam, MAKEWPARAM(1001, EN_SETFOCUS) }, { EM_SETSEL, sent|defwinproc|wparam|lparam, 0, INT_MAX }, { WM_CTLCOLOREDIT, sent|defwinproc|optional },/* Not sent on W2000, XP or Server 2003 */ { WM_CTLCOLOREDIT, sent|parent|optional },/* Not sent on W2000, XP or Server 2003 */ { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_COMBOBOX, CBN_SETFOCUS) }, { 0 }};
static const struct message SetFocusButtonSeq[] ={ { WM_KILLFOCUS, sent }, { CB_GETCOMBOBOXINFO, sent|optional },/* Windows 2000 */ { 0x0167, sent|optional },/* Undocumented message. Sent on all versions except Windows 2000 */ { WM_LBUTTONUP, sent|defwinproc }, { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_COMBOBOX, CBN_SELENDCANCEL) }, { EM_SETSEL, sent|defwinproc|wparam|lparam, 0, 0 }, { WM_CTLCOLOREDIT, sent|defwinproc|optional },/* Not sent on W2000, XP or Server 2003 */ { WM_CTLCOLOREDIT, sent|parent|optional },/* Not sent on W2000, XP or Server 2003 */ { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_COMBOBOX, CBN_KILLFOCUS) }, { WM_CTLCOLORBTN, sent|parent }, { 0 }};
static const struct message SetFocusComboBoxSeq[] ={ { WM_CTLCOLORBTN, sent|parent }, { WM_SETFOCUS, sent }, { WM_KILLFOCUS, sent|defwinproc }, { WM_SETFOCUS, sent }, { WM_COMMAND, sent|defwinproc|wparam, MAKEWPARAM(1001, EN_SETFOCUS) }, { EM_SETSEL, sent|defwinproc|wparam|lparam, 0, INT_MAX }, { WM_CTLCOLOREDIT, sent|defwinproc|optional },/* Not sent on W2000, XP or Server 2003 */ { WM_CTLCOLOREDIT, sent|parent|optional },/* Not sent on W2000, XP or Server 2003 */ { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_COMBOBOX, CBN_SETFOCUS) }, { 0 }};
static const struct message SetFocusButtonSeq2[] ={ { WM_KILLFOCUS, sent }, { CB_GETCOMBOBOXINFO, sent|optional },/* Windows 2000 */ { 0x0167, sent|optional },/* Undocumented message. Sent on all versions except Windows 2000 */ { WM_LBUTTONUP, sent|defwinproc }, { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_COMBOBOX, CBN_SELENDCANCEL) }, { EM_SETSEL, sent|defwinproc|wparam|lparam, 0, 0 }, { WM_CTLCOLOREDIT, sent|defwinproc }, { WM_CTLCOLOREDIT, sent|parent }, { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_COMBOBOX, CBN_KILLFOCUS) }, { WM_CTLCOLORBTN, sent|parent }, { 0 }};
static WNDPROC old_combobox_proc, edit_window_proc, lbox_window_proc;
static LRESULT CALLBACK combobox_edit_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ static LONG defwndproc_counter = 0; LRESULT ret; struct recvd_message msg;
/* do not log painting messages */ if (message != WM_PAINT && message != WM_NCPAINT && message != WM_SYNCPAINT && message != WM_ERASEBKGND && message != WM_NCHITTEST && message != WM_GETTEXT && !ignore_message( message )) { msg.hwnd = hwnd; msg.message = message; msg.flags = sent|wparam|lparam; if (defwndproc_counter) msg.flags |= defwinproc; msg.wParam = wParam; msg.lParam = lParam; msg.descr = "combo edit"; add_message(&msg); }
defwndproc_counter++; ret = CallWindowProcA(edit_window_proc, hwnd, message, wParam, lParam); defwndproc_counter--;
return ret;}
static LRESULT CALLBACK combobox_lbox_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ static LONG defwndproc_counter = 0; LRESULT ret; struct recvd_message msg;
/* do not log painting messages */ if (message != WM_PAINT && message != WM_NCPAINT && message != WM_SYNCPAINT && message != WM_ERASEBKGND && message != WM_NCHITTEST && !ignore_message( message )) { msg.hwnd = hwnd; msg.message = message; msg.flags = sent|wparam|lparam; if (defwndproc_counter) msg.flags |= defwinproc; msg.wParam = wParam; msg.lParam = lParam; msg.descr = "combo lbox"; add_message(&msg); }
defwndproc_counter++; ret = CallWindowProcA(lbox_window_proc, hwnd, message, wParam, lParam); defwndproc_counter--;
return ret;}
static LRESULT CALLBACK combobox_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ static LONG defwndproc_counter = 0; LRESULT ret; struct recvd_message msg;
/* do not log painting messages */ if (message != WM_PAINT && message != WM_NCPAINT && message != WM_SYNCPAINT && message != WM_ERASEBKGND && message != WM_NCHITTEST && message != WM_GETTEXT && !ignore_message( message )) { msg.hwnd = hwnd; msg.message = message; msg.flags = sent|wparam|lparam; if (defwndproc_counter) msg.flags |= defwinproc; msg.wParam = wParam; msg.lParam = lParam; msg.descr = "combo"; add_message(&msg); }
defwndproc_counter++; ret = CallWindowProcA(old_combobox_proc, hwnd, message, wParam, lParam); defwndproc_counter--;
return ret;}
static void subclass_combobox(void){ WNDCLASSA cls;
if (!GetClassInfoA(0, "ComboBox", &cls)) assert(0);
old_combobox_proc = cls.lpfnWndProc;
cls.hInstance = GetModuleHandleA(NULL); cls.lpfnWndProc = combobox_hook_proc; cls.lpszClassName = "my_combobox_class"; UnregisterClassA(cls.lpszClassName, cls.hInstance); if (!RegisterClassA(&cls)) assert(0);}
static void test_combobox_messages(void){ HWND parent, combo, button, edit, lbox; LRESULT ret; COMBOBOXINFO cbInfo; BOOL res;
subclass_combobox();
parent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 200, 200, 0, 0, 0, NULL); ok(parent != 0, "Failed to create parent window\n"); flush_sequence();
combo = CreateWindowExA(0, "my_combobox_class", "test", WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | CBS_HASSTRINGS, 0, 0, 100, 150, parent, (HMENU)ID_COMBOBOX, 0, NULL); ok(combo != 0, "Failed to create combobox window\n");
UpdateWindow(combo);
ret = SendMessageA(combo, WM_GETDLGCODE, 0, 0); ok(ret == (DLGC_WANTCHARS | DLGC_WANTARROWS), "wrong dlg_code %08lx\n", ret);
ret = SendMessageA(combo, CB_ADDSTRING, 0, (LPARAM)"item 0"); ok(ret == 0, "expected 0, got %ld\n", ret); ret = SendMessageA(combo, CB_ADDSTRING, 0, (LPARAM)"item 1"); ok(ret == 1, "expected 1, got %ld\n", ret); ret = SendMessageA(combo, CB_ADDSTRING, 0, (LPARAM)"item 2"); ok(ret == 2, "expected 2, got %ld\n", ret);
SendMessageA(combo, CB_SETCURSEL, 0, 0); SetFocus(combo); flush_sequence();
log_all_parent_messages++; SendMessageA(combo, WM_KEYDOWN, VK_DOWN, 0); SendMessageA(combo, WM_KEYUP, VK_DOWN, 0); log_all_parent_messages--; ok_sequence(WmKeyDownComboSeq, "WM_KEYDOWN/VK_DOWN on a ComboBox", FALSE);
flush_sequence(); SetWindowPos(combo, 0, 10, 10, 120, 130, SWP_NOZORDER); ok_sequence(WmSetPosComboSeq, "repositioning messages on a ComboBox", FALSE);
DestroyWindow(combo); DestroyWindow(parent);
/* Start again. Test combobox text selection when getting and losing focus */ parent = CreateWindowExA(0, "TestParentClass", "Parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 10, 10, 300, 300, NULL, NULL, NULL, NULL); ok(parent != 0, "Failed to create parent window\n");
combo = CreateWindowExA(0, "my_combobox_class", "test", WS_CHILD | WS_VISIBLE | CBS_DROPDOWN, 5, 5, 100, 100, parent, (HMENU)ID_COMBOBOX, NULL, NULL); ok(combo != 0, "Failed to create combobox window\n");
cbInfo.cbSize = sizeof(COMBOBOXINFO); SetLastError(0xdeadbeef); res = GetComboBoxInfo(combo, &cbInfo); ok(res, "Failed to get COMBOBOXINFO structure; LastError: %u\n", GetLastError()); edit = cbInfo.hwndItem;
edit_window_proc = (WNDPROC)SetWindowLongPtrA(edit, GWLP_WNDPROC, (ULONG_PTR)combobox_edit_subclass_proc);
button = CreateWindowExA(0, "Button", "OK", WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 5, 50, 100, 20, parent, NULL, (HINSTANCE)GetWindowLongPtrA(parent, GWLP_HINSTANCE), NULL); ok(button != 0, "Failed to create button window\n");
flush_sequence(); log_all_parent_messages++; SendMessageA(combo, WM_SETFOCUS, 0, (LPARAM)edit); log_all_parent_messages--; ok_sequence(WMSetFocusComboBoxSeq, "WM_SETFOCUS on a ComboBox", TRUE);
flush_sequence(); log_all_parent_messages++; SetFocus(button); log_all_parent_messages--; ok_sequence(SetFocusButtonSeq, "SetFocus on a Button", TRUE);
SendMessageA(combo, WM_SETTEXT, 0, (LPARAM)"Wine Test");
flush_sequence(); log_all_parent_messages++; SetFocus(combo); log_all_parent_messages--; ok_sequence(SetFocusComboBoxSeq, "SetFocus on a ComboBox", TRUE);
flush_sequence(); log_all_parent_messages++; SetFocus(button); log_all_parent_messages--; ok_sequence(SetFocusButtonSeq2, "SetFocus on a Button (2)", TRUE);
SetFocus(combo); SendMessageA(combo, WM_SETREDRAW, FALSE, 0); flush_sequence(); log_all_parent_messages++; SendMessageA(combo, CB_SETCURSEL, 0, 0); log_all_parent_messages--; ok_sequence(SetCurSelComboSeq_edit, "CB_SETCURSEL on a ComboBox with edit control", FALSE);
DestroyWindow(button); DestroyWindow(combo);
combo = CreateWindowExA(0, "my_combobox_class", "test", WS_CHILD | WS_VISIBLE | CBS_OWNERDRAWFIXED | CBS_DROPDOWNLIST, 5, 5, 100, 100, parent, (HMENU)ID_COMBOBOX, NULL, NULL); ok(combo != 0, "Failed to create combobox window\n");
ret = SendMessageA(combo, CB_ADDSTRING, 0, (LPARAM)"item 0"); ok(ret == 0, "expected 0, got %ld\n", ret);
cbInfo.cbSize = sizeof(COMBOBOXINFO); SetLastError(0xdeadbeef); res = GetComboBoxInfo(combo, &cbInfo); ok(res, "Failed to get COMBOBOXINFO structure; LastError: %u\n", GetLastError()); lbox = cbInfo.hwndList; lbox_window_proc = (WNDPROC)SetWindowLongPtrA(lbox, GWLP_WNDPROC, (ULONG_PTR)combobox_lbox_subclass_proc); flush_sequence();
log_all_parent_messages++; SendMessageA(combo, CB_SETCURSEL, 0, 0); log_all_parent_messages--; ok_sequence(SetCurSelComboSeq, "CB_SETCURSEL on a ComboBox", FALSE);
ShowWindow(combo, SW_HIDE); flush_sequence(); log_all_parent_messages++; SendMessageA(combo, CB_SETCURSEL, 0, 0); log_all_parent_messages--; ok_sequence(SetCurSelComboSeq2, "CB_SETCURSEL on a ComboBox", FALSE);
DestroyWindow(combo); DestroyWindow(parent);}
/****************** WM_IME_KEYDOWN message test *******************/
static const struct message WmImeKeydownMsgSeq_0[] ={ { WM_IME_KEYDOWN, wparam, VK_RETURN }, { WM_CHAR, wparam, 'A' }, { 0 }};
static const struct message WmImeKeydownMsgSeq_1[] ={ { WM_KEYDOWN, optional|wparam, VK_RETURN }, { WM_CHAR, optional|wparam, VK_RETURN }, { 0 }};
static LRESULT WINAPI wmime_keydown_procA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ struct recvd_message msg;
msg.hwnd = hwnd; msg.message = message; msg.flags = wparam|lparam; msg.wParam = wParam; msg.lParam = lParam; msg.descr = "wmime_keydown"; add_message(&msg);
return DefWindowProcA(hwnd, message, wParam, lParam);}
static void register_wmime_keydown_class(void){ WNDCLASSA cls;
ZeroMemory(&cls, sizeof(WNDCLASSA)); cls.lpfnWndProc = wmime_keydown_procA; cls.hInstance = GetModuleHandleA(0); cls.lpszClassName = "wmime_keydown_class"; if (!RegisterClassA(&cls)) assert(0);}
static void test_wmime_keydown_message(void){ HWND hwnd; MSG msg;
trace("Message sequences by WM_IME_KEYDOWN\n");
register_wmime_keydown_class(); hwnd = CreateWindowExA(0, "wmime_keydown_class", NULL, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0, NULL, NULL, 0); flush_events(); flush_sequence();
SendMessageA(hwnd, WM_IME_KEYDOWN, VK_RETURN, 0x1c0001); SendMessageA(hwnd, WM_CHAR, 'A', 1); ok_sequence(WmImeKeydownMsgSeq_0, "WM_IME_KEYDOWN 0", FALSE);
while ( PeekMessageA(&msg, 0, 0, 0, PM_REMOVE) ) { TranslateMessage(&msg); DispatchMessageA(&msg); } ok_sequence(WmImeKeydownMsgSeq_1, "WM_IME_KEYDOWN 1", FALSE);
DestroyWindow(hwnd);}
/************* painting message test ********************/
void dump_region(HRGN hrgn){ DWORD i, size; RGNDATA *data = NULL; RECT *rect;
if (!hrgn) { printf( "null region\n" ); return; } if (!(size = GetRegionData( hrgn, 0, NULL ))) return; if (!(data = HeapAlloc( GetProcessHeap(), 0, size ))) return; GetRegionData( hrgn, size, data ); printf("%d rects:", data->rdh.nCount ); for (i = 0, rect = (RECT *)data->Buffer; i < data->rdh.nCount; i++, rect++) printf( " %s", wine_dbgstr_rect( rect )); printf("\n"); HeapFree( GetProcessHeap(), 0, data );}
#define check_update_rgn( hwnd, hrgn ) check_update_rgn_( __LINE__, hwnd, hrgn )static void check_update_rgn_( int line, HWND hwnd, HRGN hrgn ){ INT ret; RECT r1, r2; HRGN tmp = CreateRectRgn( 0, 0, 0, 0 ); HRGN update = CreateRectRgn( 0, 0, 0, 0 );
ret = GetUpdateRgn( hwnd, update, FALSE ); ok( ret != ERROR, "GetUpdateRgn failed\n" ); if (ret == NULLREGION) { ok_(__FILE__,line)( !hrgn, "Update region shouldn't be empty\n" ); } else { if (CombineRgn( tmp, hrgn, update, RGN_XOR ) != NULLREGION) { ok_(__FILE__,line)( 0, "Regions are different\n" ); if (winetest_debug > 0) { printf( "Update region: " ); dump_region( update ); printf( "Wanted region: " ); dump_region( hrgn ); } } } GetRgnBox( update, &r1 ); GetUpdateRect( hwnd, &r2, FALSE ); ok_(__FILE__,line)( EqualRect( &r1, &r2 ), "Rectangles are different: %s / %s\n", wine_dbgstr_rect( &r1 ), wine_dbgstr_rect( &r2 ));
DeleteObject( tmp ); DeleteObject( update );}
static const struct message WmInvalidateRgn[] = { { WM_NCPAINT, sent }, { WM_GETTEXT, sent|defwinproc|optional }, { 0 }};
static const struct message WmGetUpdateRect[] = { { WM_NCPAINT, sent }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_PAINT, sent }, { 0 }};
static const struct message WmInvalidateFull[] = { { WM_NCPAINT, sent|wparam, 1 }, { WM_GETTEXT, sent|defwinproc|optional }, { 0 }};
static const struct message WmInvalidateErase[] = { { WM_NCPAINT, sent|wparam, 1 }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent }, { 0 }};
static const struct message WmInvalidatePaint[] = { { WM_PAINT, sent }, { WM_NCPAINT, sent|wparam|beginpaint, 1 }, { WM_GETTEXT, sent|beginpaint|defwinproc|optional }, { 0 }};
static const struct message WmInvalidateErasePaint[] = { { WM_PAINT, sent }, { WM_NCPAINT, sent|wparam|beginpaint, 1 }, { WM_GETTEXT, sent|beginpaint|defwinproc|optional }, { WM_ERASEBKGND, sent|beginpaint|optional }, { 0 }};
static const struct message WmInvalidateErasePaint2[] = { { WM_PAINT, sent }, { WM_NCPAINT, sent|beginpaint }, { WM_GETTEXT, sent|beginpaint|defwinproc|optional }, { WM_ERASEBKGND, sent|beginpaint|optional }, { 0 }};
static const struct message WmErase[] = { { WM_ERASEBKGND, sent }, { 0 }};
static const struct message WmPaint[] = { { WM_PAINT, sent }, { 0 }};
static const struct message WmParentOnlyPaint[] = { { WM_PAINT, sent|parent }, { 0 }};
static const struct message WmInvalidateParent[] = { { WM_NCPAINT, sent|parent }, { WM_GETTEXT, sent|defwinproc|parent|optional }, { WM_ERASEBKGND, sent|parent }, { 0 }};
static const struct message WmInvalidateParentChild[] = { { WM_NCPAINT, sent|parent }, { WM_GETTEXT, sent|defwinproc|parent|optional }, { WM_ERASEBKGND, sent|parent }, { WM_NCPAINT, sent }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent }, { 0 }};
static const struct message WmInvalidateParentChild2[] = { { WM_ERASEBKGND, sent|parent }, { WM_NCPAINT, sent }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent }, { 0 }};
static const struct message WmParentPaint[] = { { WM_PAINT, sent|parent }, { WM_PAINT, sent }, { 0 }};
static const struct message WmParentPaintNc[] = { { WM_PAINT, sent|parent }, { WM_PAINT, sent }, { WM_NCPAINT, sent|beginpaint }, { WM_GETTEXT, sent|beginpaint|defwinproc|optional }, { WM_ERASEBKGND, sent|beginpaint|optional }, { 0 }};
static const struct message WmChildPaintNc[] = { { WM_PAINT, sent }, { WM_NCPAINT, sent|beginpaint }, { WM_GETTEXT, sent|beginpaint|defwinproc|optional }, { WM_ERASEBKGND, sent|beginpaint|optional }, { 0 }};
static const struct message WmParentErasePaint[] = { { WM_PAINT, sent|parent }, { WM_NCPAINT, sent|parent|beginpaint }, { WM_GETTEXT, sent|parent|beginpaint|defwinproc|optional }, { WM_ERASEBKGND, sent|parent|beginpaint|optional }, { WM_PAINT, sent }, { WM_NCPAINT, sent|beginpaint }, { WM_GETTEXT, sent|beginpaint|defwinproc|optional }, { WM_ERASEBKGND, sent|beginpaint|optional }, { 0 }};
static const struct message WmParentOnlyNcPaint[] = { { WM_PAINT, sent|parent }, { WM_NCPAINT, sent|parent|beginpaint }, { WM_GETTEXT, sent|parent|beginpaint|defwinproc|optional }, { 0 }};
static const struct message WmSetParentStyle[] = { { WM_STYLECHANGING, sent|parent }, { WM_STYLECHANGED, sent|parent }, { 0 }};
static void test_paint_messages(void){ BOOL ret; RECT rect, rect2; POINT pt; MSG msg; HWND hparent, hchild; HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 ); HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 ); HWND hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW, 100, 100, 200, 200, 0, 0, 0, NULL); ok (hwnd != 0, "Failed to create overlapped window\n");
ShowWindow( hwnd, SW_SHOW ); UpdateWindow( hwnd ); flush_events(); flush_sequence();
check_update_rgn( hwnd, 0 ); SetRectRgn( hrgn, 10, 10, 20, 20 ); ret = RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE ); ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret); check_update_rgn( hwnd, hrgn ); SetRectRgn( hrgn2, 20, 20, 30, 30 ); ret = RedrawWindow( hwnd, NULL, hrgn2, RDW_INVALIDATE ); ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret); CombineRgn( hrgn, hrgn, hrgn2, RGN_OR ); check_update_rgn( hwnd, hrgn ); /* validate everything */ ret = RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE ); ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret); check_update_rgn( hwnd, 0 );
/* test empty region */ SetRectRgn( hrgn, 10, 10, 10, 15 ); ret = RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE ); ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret); check_update_rgn( hwnd, 0 ); /* test empty rect */ SetRect( &rect, 10, 10, 10, 15 ); ret = RedrawWindow( hwnd, &rect, NULL, RDW_INVALIDATE ); ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret); check_update_rgn( hwnd, 0 );
/* flush pending messages */ flush_events(); flush_sequence();
GetClientRect( hwnd, &rect ); SetRectRgn( hrgn, 0, 0, rect.right - rect.left, rect.bottom - rect.top ); /* MSDN: if hwnd parameter is NULL, InvalidateRect invalidates and redraws * all windows and sends WM_ERASEBKGND and WM_NCPAINT. */ SetRectEmpty( &rect ); ok(InvalidateRect(0, &rect, FALSE), "InvalidateRect(0, &rc, FALSE) failed\n"); check_update_rgn( hwnd, hrgn ); ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE ); flush_events(); ok_sequence( WmPaint, "Paint", FALSE ); RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE ); check_update_rgn( hwnd, 0 );
SetRectEmpty( &rect ); ok(RedrawWindow(0, &rect, 0, RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW ), "RedrawWindow failed\n"); check_update_rgn( hwnd, 0 );
SetRectEmpty( &rect ); ok(RedrawWindow(0, &rect, 0, RDW_ALLCHILDREN | RDW_VALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW ), "RedrawWindow failed\n"); check_update_rgn( hwnd, 0 );
GetWindowRect( hwnd, &rect ); ok(RedrawWindow(0, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW ), "RedrawWindow failed\n"); check_update_rgn( hwnd, 0 );
flush_events(); ok(RedrawWindow(0, &rect, 0, RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW ), "RedrawWindow failed\n"); check_update_rgn( hwnd, hrgn ); ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE ); flush_events(); ok_sequence( WmPaint, "Paint", FALSE ); RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE ); check_update_rgn( hwnd, 0 );
ok(RedrawWindow(GetDesktopWindow(), &rect, 0, RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW ), "RedrawWindow failed\n"); ret = GetUpdateRgn( hwnd, hrgn2, FALSE ); ok( ret == NULLREGION || broken(ret == SIMPLEREGION), /* <= win7 */ "region should be null (%d)\n", ret ); if (ret == SIMPLEREGION) ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE ); RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE ); flush_events();
ok(RedrawWindow(GetDesktopWindow(), NULL, 0, RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW ), "RedrawWindow failed\n"); ret = GetUpdateRgn( hwnd, hrgn2, FALSE ); ok( ret == NULLREGION || broken(ret == SIMPLEREGION), /* <= win7 */ "region should be null (%d)\n", ret ); if (ret == SIMPLEREGION) ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE ); RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE ); flush_events();
SetRectRgn( hrgn2, rect.left, rect.top, rect.right, rect.bottom ); ok(RedrawWindow(0, NULL, hrgn2, RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW ), "RedrawWindow failed\n"); check_update_rgn( hwnd, hrgn ); ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE ); flush_events(); ok_sequence( WmPaint, "Paint", FALSE ); RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE ); check_update_rgn( hwnd, 0 );
ok(RedrawWindow(0, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_ERASENOW ), "RedrawWindow failed\n"); check_update_rgn( hwnd, 0 );
ok(RedrawWindow(0, NULL, 0, RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_ERASE | RDW_ERASENOW ), "RedrawWindow failed\n"); check_update_rgn( hwnd, hrgn ); ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE ); flush_events(); ok_sequence( WmPaint, "Paint", FALSE ); RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE ); check_update_rgn( hwnd, 0 );
/* MSDN: if hwnd parameter is NULL, ValidateRect invalidates and redraws * all windows and sends WM_ERASEBKGND and WM_NCPAINT. */ SetRectEmpty( &rect ); if (ValidateRect(0, &rect) && /* not supported on Win9x */ GetUpdateRect(hwnd, NULL, FALSE)) /* or >= Win 8 */ { check_update_rgn( hwnd, hrgn ); ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE ); flush_events(); ok_sequence( WmPaint, "Paint", FALSE ); RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE ); check_update_rgn( hwnd, 0 ); }
SetLastError(0xdeadbeef); ok(!InvalidateRgn(0, NULL, FALSE), "InvalidateRgn(0, NULL, FALSE) should fail\n"); ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || GetLastError() == 0xdeadbeef, "wrong error code %d\n", GetLastError()); check_update_rgn( hwnd, 0 ); flush_events(); ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE );
SetLastError(0xdeadbeef); ok(!ValidateRgn(0, NULL), "ValidateRgn(0, NULL) should fail\n"); ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || broken( GetLastError() == 0xdeadbeef ) /* win9x */, "wrong error code %d\n", GetLastError()); check_update_rgn( hwnd, 0 ); flush_events(); ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE );
SetLastError(0xdeadbeef); ok(!UpdateWindow(NULL), "UpdateWindow(NULL) should fail\n"); ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || broken( GetLastError() == 0xdeadbeef ) /* win9x */, "wrong error code %d\n", GetLastError()); check_update_rgn( hwnd, 0 ); flush_events(); ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE );
/* now with frame */ SetRectRgn( hrgn, -5, -5, 20, 20 );
/* flush pending messages */ flush_events(); flush_sequence(); RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME ); ok_sequence( WmEmptySeq, "EmptySeq", FALSE );
SetRectRgn( hrgn, 0, 0, 20, 20 ); /* GetUpdateRgn clips to client area */ check_update_rgn( hwnd, hrgn );
flush_sequence(); RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW ); ok_sequence( WmInvalidateRgn, "InvalidateRgn", FALSE );
flush_sequence(); RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW ); ok_sequence( WmInvalidateFull, "InvalidateFull", FALSE );
GetClientRect( hwnd, &rect ); SetRectRgn( hrgn, rect.left, rect.top, rect.right, rect.bottom ); check_update_rgn( hwnd, hrgn );
flush_sequence(); RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW ); ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
flush_sequence(); RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASENOW | RDW_UPDATENOW ); ok_sequence( WmInvalidatePaint, "InvalidatePaint", FALSE ); check_update_rgn( hwnd, 0 );
flush_sequence(); RedrawWindow( hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_UPDATENOW ); ok_sequence( WmInvalidateErasePaint, "InvalidateErasePaint", FALSE ); check_update_rgn( hwnd, 0 );
flush_sequence(); SetRectRgn( hrgn, 0, 0, 100, 100 ); RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE ); SetRectRgn( hrgn, 0, 0, 50, 100 ); RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE ); SetRectRgn( hrgn, 50, 0, 100, 100 ); check_update_rgn( hwnd, hrgn ); RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_ERASENOW ); ok_sequence( WmEmptySeq, "EmptySeq", FALSE ); /* must not generate messages, everything is valid */ check_update_rgn( hwnd, 0 );
flush_sequence(); SetRectRgn( hrgn, 0, 0, 100, 100 ); RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_ERASE ); SetRectRgn( hrgn, 0, 0, 100, 50 ); RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_ERASENOW ); ok_sequence( WmErase, "Erase", FALSE ); SetRectRgn( hrgn, 0, 50, 100, 100 ); check_update_rgn( hwnd, hrgn );
flush_sequence(); SetRectRgn( hrgn, 0, 0, 100, 100 ); RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_ERASE ); SetRectRgn( hrgn, 0, 0, 50, 50 ); RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOERASE | RDW_UPDATENOW ); ok_sequence( WmPaint, "Paint", FALSE );
flush_sequence(); SetRectRgn( hrgn, -4, -4, -2, -2 ); RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME ); SetRectRgn( hrgn, -200, -200, -198, -198 ); RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOFRAME | RDW_ERASENOW ); ok_sequence( WmEmptySeq, "EmptySeq", FALSE );
flush_sequence(); SetRectRgn( hrgn, -4, -4, -2, -2 ); RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME ); SetRectRgn( hrgn, -4, -4, -3, -3 ); RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOFRAME ); SetRectRgn( hrgn, 0, 0, 1, 1 ); RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_UPDATENOW ); ok_sequence( WmPaint, "Paint", FALSE );
flush_sequence(); SetRectRgn( hrgn, -4, -4, -1, -1 ); RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME ); RedrawWindow( hwnd, NULL, 0, RDW_ERASENOW ); /* make sure no WM_PAINT was generated */ flush_events(); ok_sequence( WmInvalidateRgn, "InvalidateRgn", FALSE );
flush_sequence(); SetRectRgn( hrgn, -4, -4, -1, -1 ); RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME ); while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) { if (msg.hwnd == hwnd && msg.message == WM_PAINT) { /* GetUpdateRgn must return empty region since only nonclient area is invalidated */ INT ret = GetUpdateRgn( hwnd, hrgn, FALSE ); ok( ret == NULLREGION, "Invalid GetUpdateRgn result %d\n", ret ); ret = GetUpdateRect( hwnd, &rect, FALSE ); ok( ret, "Invalid GetUpdateRect result %d\n", ret ); /* this will send WM_NCPAINT and validate the non client area */ ret = GetUpdateRect( hwnd, &rect, TRUE ); ok( !ret, "Invalid GetUpdateRect result %d\n", ret ); } DispatchMessageA( &msg ); } ok_sequence( WmGetUpdateRect, "GetUpdateRect", FALSE );
DestroyWindow( hwnd );
/* now test with a child window */
hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW, 100, 100, 200, 200, 0, 0, 0, NULL); ok (hparent != 0, "Failed to create parent window\n");
hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE | WS_BORDER, 10, 10, 100, 100, hparent, 0, 0, NULL); ok (hchild != 0, "Failed to create child window\n");
ShowWindow( hparent, SW_SHOW ); UpdateWindow( hparent ); UpdateWindow( hchild ); flush_events(); flush_sequence(); log_all_parent_messages++;
SetRect( &rect, 0, 0, 50, 50 ); RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); RedrawWindow( hparent, NULL, 0, RDW_ERASENOW | RDW_ALLCHILDREN ); ok_sequence( WmInvalidateParentChild, "InvalidateParentChild", FALSE );
RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); pt.x = pt.y = 0; MapWindowPoints( hchild, hparent, &pt, 1 ); SetRectRgn( hrgn, 0, 0, 50 - pt.x, 50 - pt.y ); check_update_rgn( hchild, hrgn ); SetRectRgn( hrgn, 0, 0, 50, 50 ); check_update_rgn( hparent, hrgn ); RedrawWindow( hparent, NULL, 0, RDW_ERASENOW ); ok_sequence( WmInvalidateParent, "InvalidateParent", FALSE ); RedrawWindow( hchild, NULL, 0, RDW_ERASENOW ); ok_sequence( WmEmptySeq, "EraseNow child", FALSE );
flush_events(); ok_sequence( WmParentPaintNc, "WmParentPaintNc", FALSE );
RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN ); RedrawWindow( hparent, NULL, 0, RDW_ERASENOW ); ok_sequence( WmInvalidateParent, "InvalidateParent2", FALSE ); RedrawWindow( hchild, NULL, 0, RDW_ERASENOW ); ok_sequence( WmEmptySeq, "EraseNow child", FALSE );
RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE ); RedrawWindow( hparent, NULL, 0, RDW_ERASENOW | RDW_ALLCHILDREN ); ok_sequence( WmInvalidateParentChild2, "InvalidateParentChild2", FALSE );
SetWindowLongA( hparent, GWL_STYLE, GetWindowLongA(hparent,GWL_STYLE) | WS_CLIPCHILDREN ); flush_sequence(); RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN ); RedrawWindow( hparent, NULL, 0, RDW_ERASENOW ); ok_sequence( WmInvalidateParentChild, "InvalidateParentChild3", FALSE );
/* flush all paint messages */ flush_events(); flush_sequence();
/* RDW_UPDATENOW on child with WS_CLIPCHILDREN doesn't change corresponding parent area */ RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN ); SetRectRgn( hrgn, 0, 0, 50, 50 ); check_update_rgn( hparent, hrgn ); RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW ); ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE ); SetRectRgn( hrgn, 0, 0, 50, 50 ); check_update_rgn( hparent, hrgn );
/* flush all paint messages */ flush_events(); SetWindowLongA( hparent, GWL_STYLE, GetWindowLongA(hparent,GWL_STYLE) & ~WS_CLIPCHILDREN ); flush_sequence();
/* RDW_UPDATENOW on child without WS_CLIPCHILDREN will validate corresponding parent area */ RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); SetRectRgn( hrgn, 0, 0, 50, 50 ); check_update_rgn( hparent, hrgn ); RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW ); ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE ); SetRectRgn( hrgn2, 10, 10, 50, 50 ); CombineRgn( hrgn, hrgn, hrgn2, RGN_DIFF ); check_update_rgn( hparent, hrgn ); /* flush all paint messages */ flush_events(); flush_sequence();
/* same as above but parent gets completely validated */ SetRect( &rect, 20, 20, 30, 30 ); RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); SetRectRgn( hrgn, 20, 20, 30, 30 ); check_update_rgn( hparent, hrgn ); RedrawWindow( hchild, NULL, 0, RDW_UPDATENOW ); ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE ); check_update_rgn( hparent, 0 ); /* no update region */ flush_events(); ok_sequence( WmEmptySeq, "WmEmpty", FALSE ); /* and no paint messages */
/* make sure RDW_VALIDATE on child doesn't have the same effect */ flush_sequence(); RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); SetRectRgn( hrgn, 20, 20, 30, 30 ); check_update_rgn( hparent, hrgn ); RedrawWindow( hchild, NULL, 0, RDW_VALIDATE | RDW_NOERASE ); SetRectRgn( hrgn, 20, 20, 30, 30 ); check_update_rgn( hparent, hrgn );
/* same as above but normal WM_PAINT doesn't validate parent */ flush_sequence(); SetRect( &rect, 20, 20, 30, 30 ); RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); SetRectRgn( hrgn, 20, 20, 30, 30 ); check_update_rgn( hparent, hrgn ); /* no WM_PAINT in child while parent still pending */ while (PeekMessageA( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE ); while (PeekMessageA( &msg, hparent, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); ok_sequence( WmParentErasePaint, "WmParentErasePaint", FALSE );
flush_sequence(); RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); /* no WM_PAINT in child while parent still pending */ while (PeekMessageA( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE ); RedrawWindow( hparent, &rect, 0, RDW_VALIDATE | RDW_NOERASE | RDW_NOCHILDREN ); /* now that parent is valid child should get WM_PAINT */ while (PeekMessageA( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); ok_sequence( WmInvalidateErasePaint2, "WmInvalidateErasePaint2", FALSE ); while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); ok_sequence( WmEmptySeq, "No other message", FALSE );
/* same thing with WS_CLIPCHILDREN in parent */ flush_sequence(); SetWindowLongA( hparent, GWL_STYLE, GetWindowLongA(hparent,GWL_STYLE) | WS_CLIPCHILDREN ); ok_sequence( WmSetParentStyle, "WmSetParentStyle", FALSE ); /* changing style invalidates non client area, but we need to invalidate something else to see it */ RedrawWindow( hparent, &rect, 0, RDW_UPDATENOW ); ok_sequence( WmEmptySeq, "No message", FALSE ); RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_UPDATENOW ); ok_sequence( WmParentOnlyNcPaint, "WmParentOnlyNcPaint", FALSE );
flush_sequence(); RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN ); SetRectRgn( hrgn, 20, 20, 30, 30 ); check_update_rgn( hparent, hrgn ); /* no WM_PAINT in child while parent still pending */ while (PeekMessageA( &msg, hchild, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); ok_sequence( WmEmptySeq, "No WM_PAINT", FALSE ); /* WM_PAINT in parent first */ while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); ok_sequence( WmParentPaintNc, "WmParentPaintNc2", FALSE );
/* no RDW_ERASE in parent still causes RDW_ERASE and RDW_FRAME in child */ flush_sequence(); SetRect( &rect, 0, 0, 30, 30 ); RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ALLCHILDREN ); SetRectRgn( hrgn, 0, 0, 30, 30 ); check_update_rgn( hparent, hrgn ); flush_events(); ok_sequence( WmParentPaintNc, "WmParentPaintNc3", FALSE );
/* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */ flush_sequence(); SetRect( &rect, -10, 0, 30, 30 ); RedrawWindow( hchild, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE ); SetRect( &rect, 0, 0, 20, 20 ); RedrawWindow( hparent, &rect, 0, RDW_VALIDATE | RDW_ALLCHILDREN ); RedrawWindow( hparent, NULL, 0, RDW_UPDATENOW ); ok_sequence( WmChildPaintNc, "WmChildPaintNc", FALSE );
/* validate doesn't cause RDW_NOERASE or RDW_NOFRAME in child */ flush_sequence(); SetRect( &rect, -10, 0, 30, 30 ); RedrawWindow( hchild, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE ); SetRect( &rect, 0, 0, 100, 100 ); RedrawWindow( hparent, &rect, 0, RDW_VALIDATE | RDW_ALLCHILDREN ); RedrawWindow( hparent, NULL, 0, RDW_UPDATENOW ); ok_sequence( WmEmptySeq, "WmChildPaintNc2", FALSE ); RedrawWindow( hparent, NULL, 0, RDW_ERASENOW ); ok_sequence( WmEmptySeq, "WmChildPaintNc3", FALSE );
/* WS_CLIPCHILDREN doesn't exclude children from update region */ flush_sequence(); RedrawWindow( hparent, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_NOCHILDREN ); GetClientRect( hparent, &rect ); SetRectRgn( hrgn, rect.left, rect.top, rect.right, rect.bottom ); check_update_rgn( hparent, hrgn ); flush_events();
RedrawWindow( hparent, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN ); GetClientRect( hparent, &rect ); SetRectRgn( hrgn, rect.left, rect.top, rect.right, rect.bottom ); check_update_rgn( hparent, hrgn ); flush_events();
/* test RDW_INTERNALPAINT behavior */
flush_sequence(); RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT | RDW_NOCHILDREN ); flush_events(); ok_sequence( WmParentOnlyPaint, "WmParentOnlyPaint", FALSE );
RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT | RDW_ALLCHILDREN ); flush_events(); ok_sequence( WmParentPaint, "WmParentPaint", FALSE );
RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT ); flush_events(); ok_sequence( WmParentOnlyPaint, "WmParentOnlyPaint", FALSE );
assert( GetWindowLongA(hparent, GWL_STYLE) & WS_CLIPCHILDREN ); UpdateWindow( hparent ); flush_events(); flush_sequence(); trace("testing SWP_FRAMECHANGED on parent with WS_CLIPCHILDREN\n"); RedrawWindow( hchild, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED ); flush_events(); ok_sequence(WmSWP_FrameChanged_clip, "SetWindowPos:FrameChanged_clip", FALSE );
UpdateWindow( hparent ); flush_events(); flush_sequence(); trace("testing SWP_FRAMECHANGED|SWP_DEFERERASE on parent with WS_CLIPCHILDREN\n"); RedrawWindow( hchild, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_DEFERERASE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED ); flush_events(); ok_sequence(WmSWP_FrameChangedDeferErase, "SetWindowPos:FrameChangedDeferErase", FALSE );
SetWindowLongA( hparent, GWL_STYLE, GetWindowLongA(hparent,GWL_STYLE) & ~WS_CLIPCHILDREN ); ok_sequence( WmSetParentStyle, "WmSetParentStyle", FALSE ); RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT ); flush_events(); ok_sequence( WmParentPaint, "WmParentPaint", FALSE );
assert( !(GetWindowLongA(hparent, GWL_STYLE) & WS_CLIPCHILDREN) ); UpdateWindow( hparent ); flush_events(); flush_sequence(); trace("testing SWP_FRAMECHANGED on parent without WS_CLIPCHILDREN\n"); RedrawWindow( hchild, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED ); flush_events(); ok_sequence(WmSWP_FrameChanged_noclip, "SetWindowPos:FrameChanged_noclip", FALSE );
UpdateWindow( hparent ); flush_events(); flush_sequence(); trace("testing SWP_FRAMECHANGED|SWP_DEFERERASE on parent without WS_CLIPCHILDREN\n"); RedrawWindow( hchild, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_DEFERERASE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED ); flush_events(); ok_sequence(WmSWP_FrameChangedDeferErase, "SetWindowPos:FrameChangedDeferErase", FALSE );
ok(GetWindowLongA( hparent, GWL_STYLE ) & WS_VISIBLE, "parent should be visible\n"); ok(GetWindowLongA( hchild, GWL_STYLE ) & WS_VISIBLE, "child should be visible\n");
UpdateWindow( hparent ); flush_events(); flush_sequence(); trace("testing SetWindowPos(-10000, -10000) on child\n"); SetWindowPos( hchild, 0, -10000, -10000, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER ); check_update_rgn( hchild, 0 ); flush_events();
#if 0 /* this one doesn't pass under Wine yet */ UpdateWindow( hparent ); flush_events(); flush_sequence(); trace("testing ShowWindow(SW_MINIMIZE) on child\n"); ShowWindow( hchild, SW_MINIMIZE ); check_update_rgn( hchild, 0 ); flush_events();#endif
UpdateWindow( hparent ); flush_events(); flush_sequence(); trace("testing SetWindowPos(-10000, -10000) on parent\n"); SetWindowPos( hparent, 0, -10000, -10000, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER ); check_update_rgn( hparent, 0 ); flush_events();
log_all_parent_messages--; DestroyWindow( hparent ); ok(!IsWindow(hchild), "child must be destroyed with its parent\n");
/* tests for moving windows off-screen (needs simple WS_POPUP windows) */
hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_POPUP | WS_VISIBLE, 100, 100, 200, 200, 0, 0, 0, NULL); ok (hparent != 0, "Failed to create parent window\n");
hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE, 10, 10, 100, 100, hparent, 0, 0, NULL); ok (hchild != 0, "Failed to create child window\n");
ShowWindow( hparent, SW_SHOW ); UpdateWindow( hparent ); UpdateWindow( hchild ); flush_events(); flush_sequence();
/* moving child outside of parent boundaries changes update region */ SetRect( &rect, 0, 0, 40, 40 ); RedrawWindow( hchild, &rect, 0, RDW_INVALIDATE | RDW_ERASE ); SetRectRgn( hrgn, 0, 0, 40, 40 ); check_update_rgn( hchild, hrgn ); MoveWindow( hchild, -10, 10, 100, 100, FALSE ); SetRectRgn( hrgn, 10, 0, 40, 40 ); check_update_rgn( hchild, hrgn ); MoveWindow( hchild, -10, -10, 100, 100, FALSE ); SetRectRgn( hrgn, 10, 10, 40, 40 ); check_update_rgn( hchild, hrgn );
/* moving parent off-screen does too */ SetRect( &rect, 0, 0, 100, 100 ); RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_NOCHILDREN ); SetRectRgn( hrgn, 0, 0, 100, 100 ); check_update_rgn( hparent, hrgn ); SetRectRgn( hrgn, 10, 10, 40, 40 ); check_update_rgn( hchild, hrgn ); MoveWindow( hparent, -20, -20, 200, 200, FALSE ); GetUpdateRect( hparent, &rect2, FALSE ); if (!EqualRect( &rect2, &rect )) /* Win 8 and later don't crop update to screen */ { rect.left += 20; rect.top += 20; } SetRectRgn( hrgn, rect.left, rect.top, rect.right, rect.bottom ); check_update_rgn( hparent, hrgn ); SetRectRgn( hrgn, rect.left + 10, rect.top + 10, 40, 40 ); check_update_rgn( hchild, hrgn );
/* invalidated region is cropped by the parent rects */ SetRect( &rect, 0, 0, 50, 50 ); RedrawWindow( hchild, &rect, 0, RDW_INVALIDATE | RDW_ERASE ); SetRectRgn( hrgn, rect2.left + 10, rect2.top + 10, 50, 50 ); check_update_rgn( hchild, hrgn );
DestroyWindow( hparent ); ok(!IsWindow(hchild), "child must be destroyed with its parent\n"); flush_sequence();
DeleteObject( hrgn ); DeleteObject( hrgn2 );}
struct wnd_event{ HWND hwnd; HANDLE grand_child; HANDLE start_event; HANDLE stop_event;};
static DWORD WINAPI thread_proc(void *param){ MSG msg; struct wnd_event *wnd_event = param;
wnd_event->hwnd = CreateWindowExA(0, "TestWindowClass", "window caption text", WS_OVERLAPPEDWINDOW, 100, 100, 200, 200, 0, 0, 0, NULL); ok(wnd_event->hwnd != 0, "Failed to create overlapped window\n");
SetEvent(wnd_event->start_event);
while (GetMessageA(&msg, 0, 0, 0)) { TranslateMessage(&msg); DispatchMessageA(&msg); }
ok(IsWindow(wnd_event->hwnd), "window should still exist\n");
return 0;}
static DWORD CALLBACK create_grand_child_thread( void *param ){ struct wnd_event *wnd_event = param; HWND hchild; MSG msg;
hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE, 0, 0, 10, 10, wnd_event->hwnd, 0, 0, NULL); ok (hchild != 0, "Failed to create child window\n"); flush_events(); flush_sequence(); SetEvent( wnd_event->start_event );
for (;;) { MsgWaitForMultipleObjects(0, NULL, FALSE, 1000, QS_ALLINPUT); if (!IsWindow( hchild )) break; /* will be destroyed when parent thread exits */ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); } return 0;}
static DWORD CALLBACK create_child_thread( void *param ){ struct wnd_event *wnd_event = param; struct wnd_event child_event; DWORD ret, tid; MSG msg;
child_event.hwnd = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE, 0, 0, 10, 10, wnd_event->hwnd, 0, 0, NULL); ok (child_event.hwnd != 0, "Failed to create child window\n"); SetFocus( child_event.hwnd ); flush_events(); flush_sequence(); child_event.start_event = wnd_event->start_event; wnd_event->grand_child = CreateThread(NULL, 0, create_grand_child_thread, &child_event, 0, &tid); for (;;) { DWORD ret = MsgWaitForMultipleObjects(1, &child_event.start_event, FALSE, 1000, QS_SENDMESSAGE); if (ret != 1) break; while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); } ret = WaitForSingleObject( wnd_event->stop_event, 5000 ); ok( !ret, "WaitForSingleObject failed %x\n", ret ); return 0;}
static const char manifest_dep[] ="<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">""<assemblyIdentity version=\"1.2.3.4\" name=\"testdep1\" type=\"win32\" processorArchitecture=\"" ARCH "\"/>"" <file name=\"testdep.dll\" />""</assembly>";
static const char manifest_main[] ="<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">""<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\" />""<dependency>"" <dependentAssembly>"" <assemblyIdentity type=\"win32\" name=\"testdep1\" version=\"1.2.3.4\" processorArchitecture=\"" ARCH "\" />"" </dependentAssembly>""</dependency>""</assembly>";
static void create_manifest_file(const char *filename, const char *manifest){ WCHAR path[MAX_PATH]; HANDLE file; DWORD size;
MultiByteToWideChar( CP_ACP, 0, filename, -1, path, MAX_PATH ); file = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); ok(file != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError()); WriteFile(file, manifest, strlen(manifest), &size, NULL); CloseHandle(file);}
static HANDLE test_create(const char *file){ WCHAR path[MAX_PATH]; ACTCTXW actctx; HANDLE handle;
MultiByteToWideChar(CP_ACP, 0, file, -1, path, MAX_PATH); memset(&actctx, 0, sizeof(ACTCTXW)); actctx.cbSize = sizeof(ACTCTXW); actctx.lpSource = path;
handle = pCreateActCtxW(&actctx); ok(handle != INVALID_HANDLE_VALUE, "failed to create context, error %u\n", GetLastError());
ok(actctx.cbSize == sizeof(actctx), "cbSize=%d\n", actctx.cbSize); ok(actctx.dwFlags == 0, "dwFlags=%d\n", actctx.dwFlags); ok(actctx.lpSource == path, "lpSource=%p\n", actctx.lpSource); ok(actctx.wProcessorArchitecture == 0, "wProcessorArchitecture=%d\n", actctx.wProcessorArchitecture); ok(actctx.wLangId == 0, "wLangId=%d\n", actctx.wLangId); ok(actctx.lpAssemblyDirectory == NULL, "lpAssemblyDirectory=%p\n", actctx.lpAssemblyDirectory); ok(actctx.lpResourceName == NULL, "lpResourceName=%p\n", actctx.lpResourceName); ok(actctx.lpApplicationName == NULL, "lpApplicationName=%p\n", actctx.lpApplicationName); ok(actctx.hModule == NULL, "hModule=%p\n", actctx.hModule);
return handle;}
static void test_interthread_messages(void){ HANDLE hThread, context, handle, event; ULONG_PTR cookie; DWORD tid; WNDPROC proc; MSG msg; char buf[256]; int len, expected_len; struct wnd_event wnd_event; BOOL ret;
wnd_event.start_event = CreateEventW(NULL, 0, 0, NULL); if (!wnd_event.start_event) { win_skip("skipping interthread message test under win9x\n"); return; }
hThread = CreateThread(NULL, 0, thread_proc, &wnd_event, 0, &tid); ok(hThread != NULL, "CreateThread failed, error %d\n", GetLastError());
ok(WaitForSingleObject(wnd_event.start_event, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
CloseHandle(wnd_event.start_event);
SetLastError(0xdeadbeef); ok(!DestroyWindow(wnd_event.hwnd), "DestroyWindow succeeded\n"); ok(GetLastError() == ERROR_ACCESS_DENIED || GetLastError() == 0xdeadbeef, "wrong error code %d\n", GetLastError());
proc = (WNDPROC)GetWindowLongPtrA(wnd_event.hwnd, GWLP_WNDPROC); ok(proc != NULL, "GetWindowLongPtrA(GWLP_WNDPROC) error %d\n", GetLastError());
expected_len = lstrlenA("window caption text"); memset(buf, 0, sizeof(buf)); SetLastError(0xdeadbeef); len = CallWindowProcA(proc, wnd_event.hwnd, WM_GETTEXT, sizeof(buf), (LPARAM)buf); ok(len == expected_len, "CallWindowProcA(WM_GETTEXT) error %d, len %d, expected len %d\n", GetLastError(), len, expected_len); ok(!lstrcmpA(buf, "window caption text"), "window text mismatch\n");
msg.hwnd = wnd_event.hwnd; msg.message = WM_GETTEXT; msg.wParam = sizeof(buf); msg.lParam = (LPARAM)buf; memset(buf, 0, sizeof(buf)); SetLastError(0xdeadbeef); len = DispatchMessageA(&msg); ok((!len && GetLastError() == ERROR_MESSAGE_SYNC_ONLY) || broken(len), /* nt4 */ "DispatchMessageA(WM_GETTEXT) succeeded on another thread window: ret %d, error %d\n", len, GetLastError());
/* the following test causes an exception in user.exe under win9x */ msg.hwnd = wnd_event.hwnd; msg.message = WM_TIMER; msg.wParam = 0; msg.lParam = GetWindowLongPtrA(wnd_event.hwnd, GWLP_WNDPROC); SetLastError(0xdeadbeef); len = DispatchMessageA(&msg); ok(!len && GetLastError() == 0xdeadbeef, "DispatchMessageA(WM_TIMER) failed on another thread window: ret %d, error %d\n", len, GetLastError());
ret = PostMessageA(wnd_event.hwnd, WM_QUIT, 0, 0); ok( ret, "PostMessageA(WM_QUIT) error %d\n", GetLastError());
ok(WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); CloseHandle(hThread);
ok(!IsWindow(wnd_event.hwnd), "window should be destroyed on thread exit\n");
wnd_event.hwnd = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 200, 200, 0, 0, 0, NULL); ok (wnd_event.hwnd != 0, "Failed to create parent window\n"); flush_events(); flush_sequence(); log_all_parent_messages++; wnd_event.start_event = CreateEventA( NULL, TRUE, FALSE, NULL ); wnd_event.stop_event = CreateEventA( NULL, TRUE, FALSE, NULL ); hThread = CreateThread( NULL, 0, create_child_thread, &wnd_event, 0, &tid ); for (;;) { ret = MsgWaitForMultipleObjects(1, &wnd_event.start_event, FALSE, 1000, QS_SENDMESSAGE); if (ret != 1) break; while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); } ok( !ret, "MsgWaitForMultipleObjects failed %x\n", ret ); /* now wait for the thread without processing messages; this shouldn't deadlock */ SetEvent( wnd_event.stop_event ); ret = WaitForSingleObject( hThread, 5000 ); ok( !ret, "WaitForSingleObject failed %x\n", ret ); CloseHandle( hThread );
ret = WaitForSingleObject( wnd_event.grand_child, 5000 ); ok( !ret, "WaitForSingleObject failed %x\n", ret ); CloseHandle( wnd_event.grand_child );
CloseHandle( wnd_event.start_event ); CloseHandle( wnd_event.stop_event ); flush_events(); ok_sequence(WmExitThreadSeq, "destroy child on thread exit", FALSE); log_all_parent_messages--; DestroyWindow( wnd_event.hwnd );
/* activation context tests */ if (!pActivateActCtx) { win_skip("Activation contexts are not supported, skipping\n"); return; }
create_manifest_file("testdep1.manifest", manifest_dep); create_manifest_file("main.manifest", manifest_main);
context = test_create("main.manifest"); DeleteFileA("testdep1.manifest"); DeleteFileA("main.manifest");
handle = (void*)0xdeadbeef; ret = pGetCurrentActCtx(&handle); ok(ret, "GetCurrentActCtx failed: %u\n", GetLastError()); ok(handle == 0, "active context %p\n", handle);
wnd_event.start_event = CreateEventW(NULL, 0, 0, NULL); hThread = CreateThread(NULL, 0, thread_proc, &wnd_event, 0, &tid); ok(hThread != NULL, "CreateThread failed, error %d\n", GetLastError()); ok(WaitForSingleObject(wnd_event.start_event, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); CloseHandle(wnd_event.start_event);
/* context is activated after thread creation, so it doesn't inherit it by default */ ret = pActivateActCtx(context, &cookie); ok(ret, "activation failed: %u\n", GetLastError());
handle = 0; ret = pGetCurrentActCtx(&handle); ok(ret, "GetCurrentActCtx failed: %u\n", GetLastError()); ok(handle != 0, "active context %p\n", handle); pReleaseActCtx(handle);
/* destination window will test for active context */ ret = SendMessageA(wnd_event.hwnd, WM_USER+10, 0, 0); ok(ret, "thread window returned %d\n", ret);
event = CreateEventW(NULL, 0, 0, NULL); ret = PostMessageA(wnd_event.hwnd, WM_USER+10, 0, (LPARAM)event); ok(ret, "thread window returned %d\n", ret); ok(WaitForSingleObject(event, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); CloseHandle(event);
ret = PostMessageA(wnd_event.hwnd, WM_QUIT, 0, 0); ok(ret, "PostMessageA(WM_QUIT) error %d\n", GetLastError());
ok(WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); CloseHandle(hThread);
ret = pDeactivateActCtx(0, cookie); ok(ret, "DeactivateActCtx failed: %u\n", GetLastError()); pReleaseActCtx(context);}
static const struct message WmVkN[] = { { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */ { WM_KEYDOWN, wparam|lparam, 'N', 1 }, { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 }, { WM_CHAR, wparam|lparam, 'n', 1 }, { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1002,1), 0 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */ { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 }, { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 }, { 0 }};static const struct message WmShiftVkN[] = { { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 1 }, /* XP */ { WM_KEYDOWN, wparam|lparam, VK_SHIFT, 1 }, { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 1 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */ { WM_KEYDOWN, wparam|lparam, 'N', 1 }, { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 }, { WM_CHAR, wparam|lparam, 'N', 1 }, { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1001,1), 0 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */ { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 }, { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 0xc0000001 }, /* XP */ { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xc0000001 }, { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xc0000001 }, { 0 }};static const struct message WmCtrlVkN[] = { { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 1 }, /* XP */ { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 }, { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */ { WM_KEYDOWN, wparam|lparam, 'N', 1 }, { WM_KEYDOWN, sent|wparam|lparam, 'N', 1 }, { WM_CHAR, wparam|lparam, 0x000e, 1 }, { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1000,1), 0 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */ { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 }, { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 0xc0000001 }, /* XP */ { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 }, { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 }, { 0 }};static const struct message WmCtrlVkN_2[] = { { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 1 }, /* XP */ { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 }, { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */ { WM_KEYDOWN, wparam|lparam, 'N', 1 }, { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1000,1), 0 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */ { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 }, { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 0xc0000001 }, /* XP */ { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 }, { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 }, { 0 }};static const struct message WmAltVkN[] = { { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, /* XP */ { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 }, { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0x20000001 }, /* XP */ { WM_SYSKEYDOWN, wparam|lparam, 'N', 0x20000001 }, { WM_SYSKEYDOWN, sent|wparam|lparam, 'N', 0x20000001 }, { WM_SYSCHAR, wparam|lparam, 'n', 0x20000001 }, { WM_SYSCHAR, sent|wparam|lparam, 'n', 0x20000001 }, { WM_SYSCOMMAND, sent|defwinproc|wparam|lparam, SC_KEYMENU, 'n' }, { HCBT_SYSCOMMAND, hook }, { WM_ENTERMENULOOP, sent|defwinproc|wparam|lparam, 0, 0 }, { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, { 0x00AE, sent|defwinproc|optional }, /* XP */ { WM_GETTEXT, sent|defwinproc|optional }, /* XP */ { WM_INITMENU, sent|defwinproc }, { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 }, { WM_MENUCHAR, sent|defwinproc|wparam, MAKEWPARAM('n',MF_SYSMENU) }, { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 }, { WM_CAPTURECHANGED, sent|defwinproc }, { WM_MENUSELECT, sent|defwinproc|wparam, MAKEWPARAM(0,0xffff) }, { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 }, { WM_EXITMENULOOP, sent|defwinproc }, { WM_MENUSELECT, sent|defwinproc|wparam|optional, MAKEWPARAM(0,0xffff) }, /* Win95 bug */ { WM_EXITMENULOOP, sent|defwinproc|optional }, /* Win95 bug */ { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xe0000001 }, /* XP */ { WM_SYSKEYUP, wparam|lparam, 'N', 0xe0000001 }, { WM_SYSKEYUP, sent|wparam|lparam, 'N', 0xe0000001 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */ { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 }, { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 }, { 0 }};static const struct message WmAltVkN_2[] = { { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, /* XP */ { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 }, { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0x20000001 }, /* XP */ { WM_SYSKEYDOWN, wparam|lparam, 'N', 0x20000001 }, { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1003,1), 0 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xe0000001 }, /* XP */ { WM_SYSKEYUP, wparam|lparam, 'N', 0xe0000001 }, { WM_SYSKEYUP, sent|wparam|lparam, 'N', 0xe0000001 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */ { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 }, { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 }, { 0 }};static const struct message WmCtrlAltVkN[] = { { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 1 }, /* XP */ { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 }, { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, /* XP */ { WM_KEYDOWN, wparam|lparam, VK_MENU, 0x20000001 }, { WM_KEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0x20000001 }, /* XP */ { WM_KEYDOWN, wparam|lparam, 'N', 0x20000001 }, { WM_KEYDOWN, sent|wparam|lparam, 'N', 0x20000001 }, { WM_CHAR, optional }, { WM_CHAR, sent|optional }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xe0000001 }, /* XP */ { WM_KEYUP, wparam|lparam, 'N', 0xe0000001 }, { WM_KEYUP, sent|wparam|lparam, 'N', 0xe0000001 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */ { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 }, { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 0xc0000001 }, /* XP */ { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 }, { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 }, { 0 }};static const struct message WmCtrlShiftVkN[] = { { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 1 }, /* XP */ { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 }, { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 1 }, /* XP */ { WM_KEYDOWN, wparam|lparam, VK_SHIFT, 1 }, { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 1 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */ { WM_KEYDOWN, wparam|lparam, 'N', 1 }, { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1004,1), 0 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */ { WM_KEYUP, wparam|lparam, 'N', 0xc0000001 }, { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 0xc0000001 }, /* XP */ { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xc0000001 }, { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xc0000001 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 0xc0000001 }, /* XP */ { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 }, { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 }, { 0 }};static const struct message WmCtrlAltShiftVkN[] = { { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 1 }, /* XP */ { WM_KEYDOWN, wparam|lparam, VK_CONTROL, 1 }, { WM_KEYDOWN, sent|wparam|lparam, VK_CONTROL, 1 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, /* XP */ { WM_KEYDOWN, wparam|lparam, VK_MENU, 0x20000001 }, { WM_KEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 0x20000001 }, /* XP */ { WM_KEYDOWN, wparam|lparam, VK_SHIFT, 0x20000001 }, { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 0x20000001 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0x20000001 }, /* XP */ { WM_KEYDOWN, wparam|lparam, 'N', 0x20000001 }, { WM_COMMAND, sent|wparam|lparam, MAKEWPARAM(1005,1), 0 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xe0000001 }, /* XP */ { WM_KEYUP, wparam|lparam, 'N', 0xe0000001 }, { WM_KEYUP, sent|wparam|lparam, 'N', 0xe0000001 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 0xe0000001 }, /* XP */ { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xe0000001 }, { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xe0000001 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */ { WM_KEYUP, wparam|lparam, VK_MENU, 0xc0000001 }, { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_CONTROL, 0xc0000001 }, /* XP */ { WM_KEYUP, wparam|lparam, VK_CONTROL, 0xc0000001 }, { WM_KEYUP, sent|wparam|lparam, VK_CONTROL, 0xc0000001 }, { 0 }};static const struct message WmAltPressRelease[] = { { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, /* XP */ { WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0x20000001 }, { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */ { WM_SYSKEYUP, wparam|lparam, VK_MENU, 0xc0000001 }, { WM_SYSKEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 }, { WM_SYSCOMMAND, sent|defwinproc|wparam|lparam, SC_KEYMENU, 0 }, { HCBT_SYSCOMMAND, hook }, { WM_ENTERMENULOOP, sent|defwinproc|wparam|lparam, 0, 0 }, { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, { WM_INITMENU, sent|defwinproc }, { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 }, { WM_MENUSELECT, sent|defwinproc|wparam, MAKEWPARAM(0,MF_SYSMENU|MF_POPUP|MF_HILITE), 0, MAKEWPARAM(0,MF_RIGHTJUSTIFY) }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 },
{ HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x30000001 }, /* XP */
{ EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 }, { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0, }, { WM_CAPTURECHANGED, sent|defwinproc }, { WM_MENUSELECT, sent|defwinproc|wparam|optional, MAKEWPARAM(0,0xffff) }, { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 }, { WM_EXITMENULOOP, sent|defwinproc }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, /* XP */ { WM_SYSKEYUP, wparam|lparam, VK_MENU, 0xc0000001 }, { WM_SYSKEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 }, { 0 }};static const struct message WmShiftMouseButton[] = { { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 1 }, /* XP */ { WM_KEYDOWN, wparam|lparam, VK_SHIFT, 1 }, { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 1 }, { WM_MOUSEMOVE, wparam|optional, 0, 0 }, { WM_MOUSEMOVE, sent|wparam|optional, 0, 0 }, { WM_LBUTTONDOWN, wparam, MK_LBUTTON|MK_SHIFT, 0 }, { WM_LBUTTONDOWN, sent|wparam, MK_LBUTTON|MK_SHIFT, 0 }, { WM_LBUTTONUP, wparam, MK_SHIFT, 0 }, { WM_LBUTTONUP, sent|wparam, MK_SHIFT, 0 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 0xc0000001 }, /* XP */ { WM_KEYUP, wparam|lparam, VK_SHIFT, 0xc0000001 }, { WM_KEYUP, sent|wparam|lparam, VK_SHIFT, 0xc0000001 }, { 0 }};static const struct message WmF1Seq[] = { { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F1, 1 }, /* XP */ { WM_KEYDOWN, wparam|lparam, VK_F1, 1 }, { WM_KEYDOWN, sent|wparam|lparam, VK_F1, 0x00000001 }, { WM_KEYF1, wparam|lparam, 0, 0 }, { WM_KEYF1, sent|wparam|lparam, 0, 0 }, { WM_HELP, sent|defwinproc }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F1, 0xc0000001 }, /* XP */ { WM_KEYUP, wparam|lparam, VK_F1, 0xc0000001 }, { WM_KEYUP, sent|wparam|lparam, VK_F1, 0xc0000001 }, { 0 }};static const struct message WmVkAppsSeq[] = { { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_APPS, 1 }, /* XP */ { WM_KEYDOWN, wparam|lparam, VK_APPS, 1 }, { WM_KEYDOWN, sent|wparam|lparam, VK_APPS, 0x00000001 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_APPS, 0xc0000001 }, /* XP */ { WM_KEYUP, wparam|lparam, VK_APPS, 0xc0000001 }, { WM_KEYUP, sent|wparam|lparam, VK_APPS, 0xc0000001 }, { WM_CONTEXTMENU, lparam, /*hwnd*/0, -1 }, { WM_CONTEXTMENU, sent|lparam, /*hwnd*/0, -1 }, { 0 }};static const struct message WmVkF10Seq[] = { { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 1 }, /* XP */ { WM_SYSKEYDOWN, wparam|lparam, VK_F10, 1 }, { WM_SYSKEYDOWN, sent|wparam|lparam, VK_F10, 0x00000001 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 0xc0000001 }, /* XP */ { WM_SYSKEYUP, wparam|lparam, VK_F10, 0xc0000001 }, { WM_SYSKEYUP, sent|wparam|lparam, VK_F10, 0xc0000001 }, { WM_SYSCOMMAND, sent|defwinproc|wparam, SC_KEYMENU }, { HCBT_SYSCOMMAND, hook }, { WM_ENTERMENULOOP, sent|defwinproc|wparam|lparam, 0, 0 }, { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, { WM_INITMENU, sent|defwinproc }, { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 }, { WM_MENUSELECT, sent|defwinproc|wparam, MAKEWPARAM(0,MF_SYSMENU|MF_POPUP|MF_HILITE), 0, MAKEWPARAM(0,MF_RIGHTJUSTIFY) }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 },
{ HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 0x10000001 }, /* XP */
{ HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 1 }, /* XP */ { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 }, { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0, }, { WM_CAPTURECHANGED, sent|defwinproc }, { WM_MENUSELECT, sent|defwinproc|wparam|optional, MAKEWPARAM(0,0xffff) }, { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 }, { WM_EXITMENULOOP, sent|defwinproc }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 0xc0000001 }, /* XP */ { WM_SYSKEYUP, wparam|lparam, VK_F10, 0xc0000001 }, { WM_SYSKEYUP, sent|wparam|lparam, VK_F10, 0xc0000001 }, { 0 }};static const struct message WmShiftF10Seq[] = { { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 1 }, /* XP */ { WM_KEYDOWN, wparam|lparam, VK_SHIFT, 1 }, { WM_KEYDOWN, sent|wparam|lparam, VK_SHIFT, 0x00000001 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 1 }, /* XP */ { WM_SYSKEYDOWN, wparam|lparam, VK_F10, 1 }, { WM_SYSKEYDOWN, sent|wparam|lparam, VK_F10, 0x00000001 }, { WM_CONTEXTMENU, sent|defwinproc|lparam, /*hwnd*/0, -1 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 0xc0000001 }, /* XP */ { WM_SYSKEYUP, wparam|lparam, VK_F10, 0xc0000001 }, { WM_SYSKEYUP, sent|wparam|lparam, VK_F10, 0xc0000001 }, { WM_SYSCOMMAND, sent|defwinproc|wparam, SC_KEYMENU }, { HCBT_SYSCOMMAND, hook }, { WM_ENTERMENULOOP, sent|defwinproc|wparam|lparam, 0, 0 }, { WM_INITMENU, sent|defwinproc }, { WM_MENUSELECT, sent|defwinproc|wparam, MAKEWPARAM(0,MF_SYSMENU|MF_POPUP|MF_HILITE), 0, MAKEWPARAM(0,MF_RIGHTJUSTIFY) }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_SHIFT, 0xd0000001 }, /* XP */ { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_ESCAPE, 0x10000001 }, /* XP */ { WM_CAPTURECHANGED, sent|defwinproc|wparam|lparam, 0, 0 }, { WM_MENUSELECT, sent|defwinproc|wparam|lparam, 0xffff0000, 0 }, { WM_EXITMENULOOP, sent|defwinproc|wparam|lparam, 0, 0 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_ESCAPE, 0xc0000001 }, /* XP */ { WM_KEYUP, wparam|lparam, VK_ESCAPE, 0xc0000001 }, { WM_KEYUP, sent|wparam|lparam, VK_ESCAPE, 0xc0000001 }, { 0 }};
static void pump_msg_loop(HWND hwnd, HACCEL hAccel){ MSG msg;
while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) { struct recvd_message log_msg;
/* ignore some unwanted messages */ if (msg.message == WM_MOUSEMOVE || msg.message == WM_TIMER || ignore_message( msg.message )) continue;
log_msg.hwnd = msg.hwnd; log_msg.message = msg.message; log_msg.flags = wparam|lparam; log_msg.wParam = msg.wParam; log_msg.lParam = msg.lParam; log_msg.descr = "accel"; add_message(&log_msg);
if (!hAccel || !TranslateAcceleratorA(hwnd, hAccel, &msg)) { TranslateMessage(&msg); DispatchMessageA(&msg); } }}
static void test_accelerators(void){ RECT rc; POINT pt; SHORT state; HACCEL hAccel; HWND hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 200, 200, 0, 0, 0, NULL); BOOL ret;
assert(hwnd != 0); UpdateWindow(hwnd); flush_events(); flush_sequence();
SetFocus(hwnd); ok(GetFocus() == hwnd, "wrong focus window %p\n", GetFocus());
state = GetKeyState(VK_SHIFT); ok(!(state & 0x8000), "wrong Shift state %04x\n", state); state = GetKeyState(VK_CAPITAL); ok(state == 0, "wrong CapsLock state %04x\n", state);
hAccel = LoadAcceleratorsA(GetModuleHandleA(NULL), MAKEINTRESOURCEA(1)); assert(hAccel != 0);
flush_events(); pump_msg_loop(hwnd, 0); flush_sequence();
trace("testing VK_N press/release\n"); flush_sequence(); keybd_event('N', 0, 0, 0); keybd_event('N', 0, KEYEVENTF_KEYUP, 0); pump_msg_loop(hwnd, hAccel); if (!sequence_cnt) /* we didn't get any message */ { skip( "queuing key events not supported\n" ); goto done; } ok_sequence(WmVkN, "VK_N press/release", FALSE);
trace("testing Shift+VK_N press/release\n"); flush_sequence(); keybd_event(VK_SHIFT, 0, 0, 0); keybd_event('N', 0, 0, 0); keybd_event('N', 0, KEYEVENTF_KEYUP, 0); keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0); pump_msg_loop(hwnd, hAccel); ok_sequence(WmShiftVkN, "Shift+VK_N press/release", FALSE);
trace("testing Ctrl+VK_N press/release\n"); flush_sequence(); keybd_event(VK_CONTROL, 0, 0, 0); keybd_event('N', 0, 0, 0); keybd_event('N', 0, KEYEVENTF_KEYUP, 0); keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); pump_msg_loop(hwnd, hAccel); ok_sequence(WmCtrlVkN, "Ctrl+VK_N press/release", FALSE);
trace("testing Alt+VK_N press/release\n"); flush_sequence(); keybd_event(VK_MENU, 0, 0, 0); keybd_event('N', 0, 0, 0); keybd_event('N', 0, KEYEVENTF_KEYUP, 0); keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); pump_msg_loop(hwnd, hAccel); ok_sequence(WmAltVkN, "Alt+VK_N press/release", FALSE);
trace("testing Ctrl+Alt+VK_N press/release 1\n"); flush_sequence(); keybd_event(VK_CONTROL, 0, 0, 0); keybd_event(VK_MENU, 0, 0, 0); keybd_event('N', 0, 0, 0); keybd_event('N', 0, KEYEVENTF_KEYUP, 0); keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); pump_msg_loop(hwnd, hAccel); ok_sequence(WmCtrlAltVkN, "Ctrl+Alt+VK_N press/release 1", FALSE);
ret = DestroyAcceleratorTable(hAccel); ok( ret, "DestroyAcceleratorTable error %d\n", GetLastError());
hAccel = LoadAcceleratorsA(GetModuleHandleA(NULL), MAKEINTRESOURCEA(2)); assert(hAccel != 0);
trace("testing VK_N press/release\n"); flush_sequence(); keybd_event('N', 0, 0, 0); keybd_event('N', 0, KEYEVENTF_KEYUP, 0); pump_msg_loop(hwnd, hAccel); ok_sequence(WmVkN, "VK_N press/release", FALSE);
trace("testing Shift+VK_N press/release\n"); flush_sequence(); keybd_event(VK_SHIFT, 0, 0, 0); keybd_event('N', 0, 0, 0); keybd_event('N', 0, KEYEVENTF_KEYUP, 0); keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0); pump_msg_loop(hwnd, hAccel); ok_sequence(WmShiftVkN, "Shift+VK_N press/release", FALSE);
trace("testing Ctrl+VK_N press/release 2\n"); flush_sequence(); keybd_event(VK_CONTROL, 0, 0, 0); keybd_event('N', 0, 0, 0); keybd_event('N', 0, KEYEVENTF_KEYUP, 0); keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); pump_msg_loop(hwnd, hAccel); ok_sequence(WmCtrlVkN_2, "Ctrl+VK_N press/release 2", FALSE);
trace("testing Alt+VK_N press/release 2\n"); flush_sequence(); keybd_event(VK_MENU, 0, 0, 0); keybd_event('N', 0, 0, 0); keybd_event('N', 0, KEYEVENTF_KEYUP, 0); keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); pump_msg_loop(hwnd, hAccel); ok_sequence(WmAltVkN_2, "Alt+VK_N press/release 2", FALSE);
trace("testing Ctrl+Alt+VK_N press/release 2\n"); flush_sequence(); keybd_event(VK_CONTROL, 0, 0, 0); keybd_event(VK_MENU, 0, 0, 0); keybd_event('N', 0, 0, 0); keybd_event('N', 0, KEYEVENTF_KEYUP, 0); keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); pump_msg_loop(hwnd, hAccel); ok_sequence(WmCtrlAltVkN, "Ctrl+Alt+VK_N press/release 2", FALSE);
trace("testing Ctrl+Shift+VK_N press/release\n"); flush_sequence(); keybd_event(VK_CONTROL, 0, 0, 0); keybd_event(VK_SHIFT, 0, 0, 0); keybd_event('N', 0, 0, 0); keybd_event('N', 0, KEYEVENTF_KEYUP, 0); keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0); keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); pump_msg_loop(hwnd, hAccel); ok_sequence(WmCtrlShiftVkN, "Ctrl+Shift+VK_N press/release", FALSE);
trace("testing Ctrl+Alt+Shift+VK_N press/release\n"); flush_sequence(); keybd_event(VK_CONTROL, 0, 0, 0); keybd_event(VK_MENU, 0, 0, 0); keybd_event(VK_SHIFT, 0, 0, 0); keybd_event('N', 0, 0, 0); keybd_event('N', 0, KEYEVENTF_KEYUP, 0); keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0); keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); pump_msg_loop(hwnd, hAccel); ok_sequence(WmCtrlAltShiftVkN, "Ctrl+Alt+Shift+VK_N press/release", FALSE);
ret = DestroyAcceleratorTable(hAccel); ok( ret, "DestroyAcceleratorTable error %d\n", GetLastError()); hAccel = 0;
trace("testing Alt press/release\n"); flush_sequence(); keybd_event(VK_MENU, 0, 0, 0); keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); keybd_event(VK_MENU, 0, 0, 0); keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); pump_msg_loop(hwnd, 0); /* this test doesn't pass in Wine for managed windows */ ok_sequence(WmAltPressRelease, "Alt press/release", TRUE);
trace("testing VK_F1 press/release\n"); keybd_event(VK_F1, 0, 0, 0); keybd_event(VK_F1, 0, KEYEVENTF_KEYUP, 0); pump_msg_loop(hwnd, 0); ok_sequence(WmF1Seq, "F1 press/release", FALSE);
trace("testing VK_APPS press/release\n"); keybd_event(VK_APPS, 0, 0, 0); keybd_event(VK_APPS, 0, KEYEVENTF_KEYUP, 0); pump_msg_loop(hwnd, 0); ok_sequence(WmVkAppsSeq, "VK_APPS press/release", FALSE);
trace("testing VK_F10 press/release\n"); keybd_event(VK_F10, 0, 0, 0); keybd_event(VK_F10, 0, KEYEVENTF_KEYUP, 0); keybd_event(VK_F10, 0, 0, 0); keybd_event(VK_F10, 0, KEYEVENTF_KEYUP, 0); pump_msg_loop(hwnd, 0); ok_sequence(WmVkF10Seq, "VK_F10 press/release", TRUE);
trace("testing SHIFT+F10 press/release\n"); keybd_event(VK_SHIFT, 0, 0, 0); keybd_event(VK_F10, 0, 0, 0); keybd_event(VK_F10, 0, KEYEVENTF_KEYUP, 0); keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0); keybd_event(VK_ESCAPE, 0, 0, 0); keybd_event(VK_ESCAPE, 0, KEYEVENTF_KEYUP, 0); pump_msg_loop(hwnd, 0); ok_sequence(WmShiftF10Seq, "SHIFT+F10 press/release", TRUE);
trace("testing Shift+MouseButton press/release\n"); /* first, move mouse pointer inside of the window client area */ GetClientRect(hwnd, &rc); MapWindowPoints(hwnd, 0, (LPPOINT)&rc, 2); rc.left += (rc.right - rc.left)/2; rc.top += (rc.bottom - rc.top)/2; SetCursorPos(rc.left, rc.top); SetActiveWindow(hwnd);
flush_events(); flush_sequence(); GetCursorPos(&pt); if (pt.x == rc.left && pt.y == rc.top) { int i; keybd_event(VK_SHIFT, 0, 0, 0); mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0); pump_msg_loop(hwnd, 0); for (i = 0; i < sequence_cnt; i++) if (sequence[i].message == WM_LBUTTONDOWN) break; if (i < sequence_cnt) ok_sequence(WmShiftMouseButton, "Shift+MouseButton press/release", FALSE); else skip( "Shift+MouseButton event didn't get to the window\n" ); }
done: if (hAccel) DestroyAcceleratorTable(hAccel); DestroyWindow(hwnd);}
/************* window procedures ********************/
static LRESULT MsgCheckProc (BOOL unicode, HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ static LONG defwndproc_counter = 0; static LONG beginpaint_counter = 0; LRESULT ret; struct recvd_message msg;
if (ignore_message( message )) return 0;
switch (message) { case WM_ENABLE: { LONG style = GetWindowLongA(hwnd, GWL_STYLE); ok((BOOL)wParam == !(style & WS_DISABLED), "wrong WS_DISABLED state: %ld != %d\n", wParam, !(style & WS_DISABLED)); break; }
case WM_CAPTURECHANGED: if (test_DestroyWindow_flag) { DWORD style = GetWindowLongA(hwnd, GWL_STYLE); if (style & WS_CHILD) lParam = GetWindowLongPtrA(hwnd, GWLP_ID); else if (style & WS_POPUP) lParam = WND_POPUP_ID; else lParam = WND_PARENT_ID; } break;
case WM_NCDESTROY: { HWND capture;
ok(!GetWindow(hwnd, GW_CHILD), "children should be unlinked at this point\n"); capture = GetCapture(); if (capture) { ok(capture == hwnd, "capture should NOT be released at this point (capture %p)\n", capture); trace("current capture %p, releasing...\n", capture); ReleaseCapture(); } } /* fall through */ case WM_DESTROY: if (pGetAncestor) ok(pGetAncestor(hwnd, GA_PARENT) != 0, "parent should NOT be unlinked at this point\n"); if (test_DestroyWindow_flag) { DWORD style = GetWindowLongA(hwnd, GWL_STYLE); if (style & WS_CHILD) lParam = GetWindowLongPtrA(hwnd, GWLP_ID); else if (style & WS_POPUP) lParam = WND_POPUP_ID; else lParam = WND_PARENT_ID; } break;
/* test_accelerators() depends on this */ case WM_NCHITTEST: return HTCLIENT;
case WM_USER+10: { ACTIVATION_CONTEXT_BASIC_INFORMATION basicinfo; HANDLE handle, event = (HANDLE)lParam; BOOL ret;
handle = (void*)0xdeadbeef; ret = pGetCurrentActCtx(&handle); ok(ret, "failed to get current context, %u\n", GetLastError()); ok(handle == 0, "got active context %p\n", handle);
memset(&basicinfo, 0xff, sizeof(basicinfo)); ret = pQueryActCtxW(QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX, handle, 0, ActivationContextBasicInformation, &basicinfo, sizeof(basicinfo), NULL); ok(ret, "got %d, error %d\n", ret, GetLastError()); ok(basicinfo.hActCtx == NULL, "got %p\n", basicinfo.hActCtx); ok(basicinfo.dwFlags == 0, "got %x\n", basicinfo.dwFlags);
if (event) SetEvent(event); return 1; }
/* ignore */ case WM_MOUSEMOVE: case WM_MOUSEACTIVATE: case WM_NCMOUSEMOVE: case WM_SETCURSOR: case WM_IME_SELECT: return 0; }
msg.hwnd = hwnd; msg.message = message; msg.flags = sent|wparam|lparam; if (defwndproc_counter) msg.flags |= defwinproc; if (beginpaint_counter) msg.flags |= beginpaint; msg.wParam = wParam; msg.lParam = lParam; msg.descr = "MsgCheckProc"; add_message(&msg);
if (message == WM_GETMINMAXINFO && (GetWindowLongA(hwnd, GWL_STYLE) & WS_CHILD)) { HWND parent = GetParent(hwnd); RECT rc; MINMAXINFO *minmax = (MINMAXINFO *)lParam;
GetClientRect(parent, &rc); trace("parent %p client size = (%d x %d)\n", parent, rc.right, rc.bottom); trace("Reserved=%d,%d MaxSize=%d,%d MaxPos=%d,%d MinTrack=%d,%d MaxTrack=%d,%d\n", minmax->ptReserved.x, minmax->ptReserved.y, minmax->ptMaxSize.x, minmax->ptMaxSize.y, minmax->ptMaxPosition.x, minmax->ptMaxPosition.y, minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y, minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y);
ok(minmax->ptMaxSize.x == rc.right, "default width of maximized child %d != %d\n", minmax->ptMaxSize.x, rc.right); ok(minmax->ptMaxSize.y == rc.bottom, "default height of maximized child %d != %d\n", minmax->ptMaxSize.y, rc.bottom); }
if (message == WM_PAINT) { PAINTSTRUCT ps; beginpaint_counter++; BeginPaint( hwnd, &ps ); beginpaint_counter--; EndPaint( hwnd, &ps ); return 0; }
if (!test_context_menu && message == WM_CONTEXTMENU) { /* don't create context menu */ return 0; }
defwndproc_counter++; ret = unicode ? DefWindowProcW(hwnd, message, wParam, lParam) : DefWindowProcA(hwnd, message, wParam, lParam); defwndproc_counter--;
return ret;}
static LRESULT WINAPI MsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ return MsgCheckProc (FALSE, hwnd, message, wParam, lParam);}
static LRESULT WINAPI MsgCheckProcW(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ return MsgCheckProc (TRUE, hwnd, message, wParam, lParam);}
static LRESULT WINAPI PopupMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ static LONG defwndproc_counter = 0; LRESULT ret; struct recvd_message msg;
if (ignore_message( message )) return 0;
switch (message) { case WM_QUERYENDSESSION: case WM_ENDSESSION: lParam &= ~0x01; /* Vista adds a 0x01 flag */ break; }
msg.hwnd = hwnd; msg.message = message; msg.flags = sent|wparam|lparam; if (defwndproc_counter) msg.flags |= defwinproc; msg.wParam = wParam; msg.lParam = lParam; msg.descr = "popup"; add_message(&msg);
if (message == WM_CREATE) { DWORD style = GetWindowLongA(hwnd, GWL_STYLE) | WS_VISIBLE; SetWindowLongA(hwnd, GWL_STYLE, style); }
defwndproc_counter++; ret = DefWindowProcA(hwnd, message, wParam, lParam); defwndproc_counter--;
return ret;}
static LRESULT WINAPI ParentMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ static LONG defwndproc_counter = 0; static LONG beginpaint_counter = 0; LRESULT ret; struct recvd_message msg;
if (ignore_message( message )) return 0;
if (log_all_parent_messages || message == WM_PARENTNOTIFY || message == WM_CANCELMODE || message == WM_SETFOCUS || message == WM_KILLFOCUS || message == WM_ENABLE || message == WM_ENTERIDLE || message == WM_DRAWITEM || message == WM_MEASUREITEM || message == WM_COMPAREITEM || message == WM_COMMAND || message == WM_IME_SETCONTEXT) { switch (message) { /* ignore */ case WM_NCHITTEST: return HTCLIENT; case WM_SETCURSOR: case WM_MOUSEMOVE: case WM_NCMOUSEMOVE: return 0;
case WM_ERASEBKGND: { RECT rc; INT ret = GetClipBox((HDC)wParam, &rc);
trace("WM_ERASEBKGND: GetClipBox()=%d, %s\n", ret, wine_dbgstr_rect(&rc)); break; } }
msg.hwnd = hwnd; msg.message = message; msg.flags = sent|parent|wparam|lparam; if (defwndproc_counter) msg.flags |= defwinproc; if (beginpaint_counter) msg.flags |= beginpaint; msg.wParam = wParam; msg.lParam = lParam; msg.descr = "parent"; add_message(&msg); }
if (message == WM_PAINT) { PAINTSTRUCT ps; beginpaint_counter++; BeginPaint( hwnd, &ps ); beginpaint_counter--; EndPaint( hwnd, &ps ); return 0; }
defwndproc_counter++; ret = DefWindowProcA(hwnd, message, wParam, lParam); defwndproc_counter--;
return message == WM_COMPAREITEM ? -1 : ret;}
static INT_PTR CALLBACK StopQuitMsgCheckProcA(HWND hwnd, UINT message, WPARAM wp, LPARAM lp){ if (message == WM_CREATE) PostMessageA(hwnd, WM_CLOSE, 0, 0); else if (message == WM_CLOSE) { /* Only the first WM_QUIT will survive the window destruction */ PostMessageA(hwnd, WM_USER, 0x1234, 0x5678); PostMessageA(hwnd, WM_QUIT, 0x1234, 0x5678); PostMessageA(hwnd, WM_QUIT, 0x4321, 0x8765); }
return DefWindowProcA(hwnd, message, wp, lp);}
static LRESULT WINAPI TestDlgProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ static LONG defwndproc_counter = 0; LRESULT ret; struct recvd_message msg;
if (ignore_message( message )) return 0;
if (test_def_id) { DefDlgProcA(hwnd, DM_SETDEFID, 1, 0); ret = DefDlgProcA(hwnd, DM_GETDEFID, 0, 0); if (after_end_dialog) ok( ret == 0, "DM_GETDEFID should return 0 after EndDialog, got %lx\n", ret ); else ok(HIWORD(ret) == DC_HASDEFID, "DM_GETDEFID should return DC_HASDEFID, got %lx\n", ret); }
msg.hwnd = hwnd; msg.message = message; msg.flags = sent|wparam|lparam; if (defwndproc_counter) msg.flags |= defwinproc; msg.wParam = wParam; msg.lParam = lParam; msg.descr = "dialog"; add_message(&msg);
defwndproc_counter++; ret = DefDlgProcA(hwnd, message, wParam, lParam); defwndproc_counter--;
return ret;}
static LRESULT WINAPI ShowWindowProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ static LONG defwndproc_counter = 0; LRESULT ret; struct recvd_message msg;
/* log only specific messages we are interested in */ switch (message) {#if 0 /* probably log these as well */ case WM_ACTIVATE: case WM_SETFOCUS: case WM_KILLFOCUS:#endif case WM_SHOWWINDOW: case WM_SIZE: case WM_MOVE: case WM_GETMINMAXINFO: case WM_WINDOWPOSCHANGING: case WM_WINDOWPOSCHANGED: break;
default: /* ignore */ /*trace("showwindow: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);*/ return DefWindowProcA(hwnd, message, wParam, lParam); }
msg.hwnd = hwnd; msg.message = message; msg.flags = sent|wparam|lparam; if (defwndproc_counter) msg.flags |= defwinproc; msg.wParam = wParam; msg.lParam = lParam; msg.descr = "show"; add_message(&msg);
defwndproc_counter++; ret = DefWindowProcA(hwnd, message, wParam, lParam); defwndproc_counter--;
return ret;}
static LRESULT WINAPI recursive_activation_wndprocA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ static LONG defwndproc_counter = 0; struct recvd_message msg; LRESULT ret;
switch (message) { /* log only specific messages we are interested in */ case WM_NCACTIVATE: case WM_ACTIVATE: case WM_SETFOCUS: case WM_KILLFOCUS: break; default: return DefWindowProcA(hwnd, message, wParam, lParam); }
msg.hwnd = hwnd; msg.message = message; msg.flags = sent|wparam|lparam; if (defwndproc_counter) msg.flags |= defwinproc; msg.wParam = wParam; msg.lParam = lParam; msg.descr = "recursive_activation"; add_message(&msg);
/* recursively activate ourselves by first losing activation and changing it back */ if (message == WM_ACTIVATE && LOWORD(wParam) != WA_INACTIVE) { SetActiveWindow((HWND)lParam); SetActiveWindow(hwnd); return 0; }
defwndproc_counter++; ret = DefWindowProcA(hwnd, message, wParam, lParam); defwndproc_counter--;
return ret;}
static LRESULT WINAPI PaintLoopProcA(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){ switch (msg) { case WM_CREATE: return 0; case WM_PAINT: { MSG msg2; static int i = 0;
if (i < 256) { i++; if (PeekMessageA(&msg2, 0, 0, 0, 1)) { TranslateMessage(&msg2); DispatchMessageA(&msg2); } i--; } else ok(broken(1), "infinite loop\n"); if ( i == 0) paint_loop_done = TRUE; return DefWindowProcA(hWnd,msg,wParam,lParam); } } return DefWindowProcA(hWnd,msg,wParam,lParam);}
static LRESULT WINAPI HotkeyMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ static LONG defwndproc_counter = 0; LRESULT ret; struct recvd_message msg; DWORD queue_status;
if (ignore_message( message )) return 0;
if ((message >= WM_KEYFIRST && message <= WM_KEYLAST) || message == WM_HOTKEY || message >= WM_APP) { msg.hwnd = hwnd; msg.message = message; msg.flags = sent|wparam|lparam; if (defwndproc_counter) msg.flags |= defwinproc; msg.wParam = wParam; msg.lParam = lParam; msg.descr = "HotkeyMsgCheckProcA"; add_message(&msg); }
defwndproc_counter++; ret = DefWindowProcA(hwnd, message, wParam, lParam); defwndproc_counter--;
if (message == WM_APP) { queue_status = GetQueueStatus(QS_HOTKEY); ok((queue_status & (QS_HOTKEY << 16)) == QS_HOTKEY << 16, "expected QS_HOTKEY << 16 set, got %x\n", queue_status); queue_status = GetQueueStatus(QS_POSTMESSAGE); ok((queue_status & (QS_POSTMESSAGE << 16)) == QS_POSTMESSAGE << 16, "expected QS_POSTMESSAGE << 16 set, got %x\n", queue_status); PostMessageA(hwnd, WM_APP+1, 0, 0); } else if (message == WM_APP+1) { queue_status = GetQueueStatus(QS_HOTKEY); ok((queue_status & (QS_HOTKEY << 16)) == 0, "expected QS_HOTKEY << 16 cleared, got %x\n", queue_status); }
return ret;}
static BOOL RegisterWindowClasses(void){ WNDCLASSA cls; WNDCLASSW clsW;
cls.style = 0; cls.lpfnWndProc = MsgCheckProcA; cls.cbClsExtra = 0; cls.cbWndExtra = 0; cls.hInstance = GetModuleHandleA(0); cls.hIcon = 0; cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); cls.hbrBackground = GetStockObject(WHITE_BRUSH); cls.lpszMenuName = NULL; cls.lpszClassName = "TestWindowClass"; if(!RegisterClassA(&cls)) return FALSE;
cls.lpfnWndProc = HotkeyMsgCheckProcA; cls.lpszClassName = "HotkeyWindowClass"; if(!RegisterClassA(&cls)) return FALSE;
cls.lpfnWndProc = ShowWindowProcA; cls.lpszClassName = "ShowWindowClass"; if(!RegisterClassA(&cls)) return FALSE;
cls.lpfnWndProc = recursive_activation_wndprocA; cls.lpszClassName = "RecursiveActivationClass"; if(!RegisterClassA(&cls)) return FALSE;
cls.lpfnWndProc = PopupMsgCheckProcA; cls.lpszClassName = "TestPopupClass"; if(!RegisterClassA(&cls)) return FALSE;
cls.lpfnWndProc = ParentMsgCheckProcA; cls.lpszClassName = "TestParentClass"; if(!RegisterClassA(&cls)) return FALSE;
cls.lpfnWndProc = StopQuitMsgCheckProcA; cls.lpszClassName = "StopQuitClass"; if(!RegisterClassA(&cls)) return FALSE;
cls.lpfnWndProc = DefWindowProcA; cls.lpszClassName = "SimpleWindowClass"; if(!RegisterClassA(&cls)) return FALSE;
cls.lpfnWndProc = PaintLoopProcA; cls.lpszClassName = "PaintLoopWindowClass"; if(!RegisterClassA(&cls)) return FALSE;
cls.style = CS_NOCLOSE; cls.lpszClassName = "NoCloseWindowClass"; if(!RegisterClassA(&cls)) return FALSE;
ok(GetClassInfoA(0, "#32770", &cls), "GetClassInfo failed\n"); cls.style = 0; cls.hInstance = GetModuleHandleA(0); cls.hbrBackground = 0; cls.lpfnWndProc = TestDlgProcA; cls.lpszClassName = "TestDialogClass"; if(!RegisterClassA(&cls)) return FALSE;
clsW.style = 0; clsW.lpfnWndProc = MsgCheckProcW; clsW.cbClsExtra = 0; clsW.cbWndExtra = 0; clsW.hInstance = GetModuleHandleW(0); clsW.hIcon = 0; clsW.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARROW); clsW.hbrBackground = GetStockObject(WHITE_BRUSH); clsW.lpszMenuName = NULL; clsW.lpszClassName = testWindowClassW; RegisterClassW(&clsW); /* ignore error, this fails on Win9x */
return TRUE;}
static BOOL is_our_logged_class(HWND hwnd){ char buf[256];
if (GetClassNameA(hwnd, buf, sizeof(buf))) { if (!lstrcmpiA(buf, "TestWindowClass") || !lstrcmpiA(buf, "ShowWindowClass") || !lstrcmpiA(buf, "RecursiveActivationClass") || !lstrcmpiA(buf, "TestParentClass") || !lstrcmpiA(buf, "TestPopupClass") || !lstrcmpiA(buf, "SimpleWindowClass") || !lstrcmpiA(buf, "TestDialogClass") || !lstrcmpiA(buf, "MDI_frame_class") || !lstrcmpiA(buf, "MDI_client_class") || !lstrcmpiA(buf, "MDI_child_class") || !lstrcmpiA(buf, "my_button_class") || !lstrcmpiA(buf, "my_edit_class") || !lstrcmpiA(buf, "static") || !lstrcmpiA(buf, "ListBox") || !lstrcmpiA(buf, "ComboBox") || !lstrcmpiA(buf, "MyDialogClass") || !lstrcmpiA(buf, "#32770") || !lstrcmpiA(buf, "#32768")) return TRUE; } return FALSE;}
static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam) { HWND hwnd;
ok(cbt_hook_thread_id == GetCurrentThreadId(), "we didn't ask for events from other threads\n");
if (nCode == HCBT_CLICKSKIPPED) { /* ignore this event, XP sends it a lot when switching focus between windows */ return CallNextHookEx(hCBT_hook, nCode, wParam, lParam); }
if (nCode == HCBT_SYSCOMMAND || nCode == HCBT_KEYSKIPPED) { struct recvd_message msg;
msg.hwnd = 0; msg.message = nCode; msg.flags = hook|wparam|lparam; msg.wParam = wParam; msg.lParam = lParam; msg.descr = "CBT"; add_message(&msg);
return CallNextHookEx(hCBT_hook, nCode, wParam, lParam); }
if (nCode == HCBT_DESTROYWND) { if (test_DestroyWindow_flag) { DWORD style = GetWindowLongA((HWND)wParam, GWL_STYLE); if (style & WS_CHILD) lParam = GetWindowLongPtrA((HWND)wParam, GWLP_ID); else if (style & WS_POPUP) lParam = WND_POPUP_ID; else lParam = WND_PARENT_ID; } }
/* Log also SetFocus(0) calls */ hwnd = wParam ? (HWND)wParam : (HWND)lParam;
if (is_our_logged_class(hwnd)) { struct recvd_message msg;
msg.hwnd = hwnd; msg.message = nCode; msg.flags = hook|wparam|lparam; msg.wParam = wParam; msg.lParam = lParam; msg.descr = "CBT"; add_message(&msg); } return CallNextHookEx(hCBT_hook, nCode, wParam, lParam);}
static void CALLBACK win_event_proc(HWINEVENTHOOK hevent, DWORD event, HWND hwnd, LONG object_id, LONG child_id, DWORD thread_id, DWORD event_time){ ok(thread_id == GetCurrentThreadId(), "we didn't ask for events from other threads\n");
/* ignore mouse cursor events */ if (object_id == OBJID_CURSOR) return;
if (!hwnd || is_our_logged_class(hwnd)) { struct recvd_message msg;
msg.hwnd = hwnd; msg.message = event; msg.flags = winevent_hook|wparam|lparam; msg.wParam = object_id; msg.lParam = child_id; msg.descr = "WEH"; add_message(&msg); }}
static const WCHAR wszUnicode[] = {'U','n','i','c','o','d','e',0};static const WCHAR wszAnsi[] = {'U',0};
static LRESULT CALLBACK MsgConversionProcW(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){ switch (uMsg) { case CB_FINDSTRINGEXACT: trace("String: %p\n", (LPCWSTR)lParam); if (!lstrcmpW((LPCWSTR)lParam, wszUnicode)) return 1; if (!lstrcmpW((LPCWSTR)lParam, wszAnsi)) return 0; return -1; } return DefWindowProcW(hwnd, uMsg, wParam, lParam);}
static const struct message WmGetTextLengthAfromW[] = { { WM_GETTEXTLENGTH, sent }, { WM_GETTEXT, sent|optional }, { 0 }};
static const WCHAR dummy_window_text[] = {'d','u','m','m','y',' ','t','e','x','t',0};
/* dummy window proc for WM_GETTEXTLENGTH test */static LRESULT CALLBACK get_text_len_proc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ){ switch(msg) { case WM_GETTEXTLENGTH: return lstrlenW(dummy_window_text) + 37; /* some random length */ case WM_GETTEXT: lstrcpynW( (LPWSTR)lp, dummy_window_text, wp ); return lstrlenW( (LPWSTR)lp ); default: return DefWindowProcW( hwnd, msg, wp, lp ); }}
static void test_message_conversion(void){ static const WCHAR wszMsgConversionClass[] = {'M','s','g','C','o','n','v','e','r','s','i','o','n','C','l','a','s','s',0}; WNDCLASSW cls; LRESULT lRes; HWND hwnd; WNDPROC wndproc, newproc; BOOL ret;
cls.style = 0; cls.lpfnWndProc = MsgConversionProcW; cls.cbClsExtra = 0; cls.cbWndExtra = 0; cls.hInstance = GetModuleHandleW(NULL); cls.hIcon = NULL; cls.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW); cls.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1); cls.lpszMenuName = NULL; cls.lpszClassName = wszMsgConversionClass; /* this call will fail on Win9x, but that doesn't matter as this test is * meaningless on those platforms */ if(!RegisterClassW(&cls)) return;
hwnd = CreateWindowExW(0, wszMsgConversionClass, NULL, WS_OVERLAPPED, 100, 100, 200, 200, 0, 0, 0, NULL); ok(hwnd != NULL, "Window creation failed\n");
/* {W, A} -> A */
wndproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_WNDPROC); lRes = CallWindowProcA(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); ok(lRes == 0, "String should have been converted\n"); lRes = CallWindowProcW(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); ok(lRes == 1, "String shouldn't have been converted\n");
/* {W, A} -> W */
wndproc = (WNDPROC)GetWindowLongPtrW(hwnd, GWLP_WNDPROC); lRes = CallWindowProcA(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); ok(lRes == 1, "String shouldn't have been converted\n"); lRes = CallWindowProcW(wndproc, hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); ok(lRes == 1, "String shouldn't have been converted\n");
/* Synchronous messages */
lRes = SendMessageA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); ok(lRes == 0, "String should have been converted\n"); lRes = SendMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); ok(lRes == 1, "String shouldn't have been converted\n");
/* Asynchronous messages */
SetLastError(0); lRes = PostMessageA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER), "PostMessage on sync only message returned %ld, last error %d\n", lRes, GetLastError()); SetLastError(0); lRes = PostMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER), "PostMessage on sync only message returned %ld, last error %d\n", lRes, GetLastError()); SetLastError(0); lRes = PostThreadMessageA(GetCurrentThreadId(), CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER), "PosThreadtMessage on sync only message returned %ld, last error %d\n", lRes, GetLastError()); SetLastError(0); lRes = PostThreadMessageW(GetCurrentThreadId(), CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER), "PosThreadtMessage on sync only message returned %ld, last error %d\n", lRes, GetLastError()); SetLastError(0); lRes = SendNotifyMessageA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER), "SendNotifyMessage on sync only message returned %ld, last error %d\n", lRes, GetLastError()); SetLastError(0); lRes = SendNotifyMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode); ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER), "SendNotifyMessage on sync only message returned %ld, last error %d\n", lRes, GetLastError()); SetLastError(0); lRes = SendMessageCallbackA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode, NULL, 0); ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER), "SendMessageCallback on sync only message returned %ld, last error %d\n", lRes, GetLastError()); SetLastError(0); lRes = SendMessageCallbackW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode, NULL, 0); ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER), "SendMessageCallback on sync only message returned %ld, last error %d\n", lRes, GetLastError());
/* Check WM_GETTEXTLENGTH A->W behaviour, whether WM_GETTEXT is also sent or not */
hwnd = CreateWindowW (testWindowClassW, wszUnicode, WS_OVERLAPPEDWINDOW, 100, 100, 200, 200, 0, 0, 0, NULL); assert(hwnd); flush_sequence(); lRes = SendMessageA (hwnd, WM_GETTEXTLENGTH, 0, 0); ok_sequence(WmGetTextLengthAfromW, "ANSI WM_GETTEXTLENGTH to Unicode window", FALSE); ok( lRes == WideCharToMultiByte( CP_ACP, 0, wszUnicode, lstrlenW(wszUnicode), NULL, 0, NULL, NULL ), "got bad length %ld\n", lRes );
flush_sequence(); lRes = CallWindowProcA( (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ), hwnd, WM_GETTEXTLENGTH, 0, 0); ok_sequence(WmGetTextLengthAfromW, "ANSI WM_GETTEXTLENGTH to Unicode window", FALSE); ok( lRes == WideCharToMultiByte( CP_ACP, 0, wszUnicode, lstrlenW(wszUnicode), NULL, 0, NULL, NULL ), "got bad length %ld\n", lRes );
wndproc = (WNDPROC)SetWindowLongPtrW( hwnd, GWLP_WNDPROC, (LONG_PTR)get_text_len_proc ); newproc = (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ); lRes = CallWindowProcA( newproc, hwnd, WM_GETTEXTLENGTH, 0, 0 ); ok( lRes == WideCharToMultiByte( CP_ACP, 0, dummy_window_text, lstrlenW(dummy_window_text), NULL, 0, NULL, NULL ) || broken(lRes == lstrlenW(dummy_window_text) + 37), "got bad length %ld\n", lRes );
SetWindowLongPtrW( hwnd, GWLP_WNDPROC, (LONG_PTR)wndproc ); /* restore old wnd proc */ lRes = CallWindowProcA( newproc, hwnd, WM_GETTEXTLENGTH, 0, 0 ); ok( lRes == WideCharToMultiByte( CP_ACP, 0, dummy_window_text, lstrlenW(dummy_window_text), NULL, 0, NULL, NULL ) || broken(lRes == lstrlenW(dummy_window_text) + 37), "got bad length %ld\n", lRes );
ret = DestroyWindow(hwnd); ok( ret, "DestroyWindow() error %d\n", GetLastError());}
struct timer_info{ HWND hWnd; HANDLE handles[2]; DWORD id;};
static VOID CALLBACK tfunc(HWND hwnd, UINT uMsg, UINT_PTR id, DWORD dwTime){}
#define TIMER_ID 0x19#define TIMER_COUNT_EXPECTED 100#define TIMER_COUNT_TOLERANCE 10
static int count = 0;static void CALLBACK callback_count(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime){ count++;}
static DWORD exception;static void CALLBACK callback_exception(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime){ count++; RaiseException(exception, 0, 0, NULL);}
static DWORD WINAPI timer_thread_proc(LPVOID x){ struct timer_info *info = x; DWORD r;
r = KillTimer(info->hWnd, 0x19); ok(r,"KillTimer failed in thread\n"); r = SetTimer(info->hWnd,TIMER_ID,10000,tfunc); ok(r,"SetTimer failed in thread\n"); ok(r==TIMER_ID,"SetTimer id different\n"); r = SetEvent(info->handles[0]); ok(r,"SetEvent failed in thread\n"); return 0;}
static void test_timers(void){ struct timer_info info; DWORD start; DWORD id; MSG msg;
info.hWnd = CreateWindowA("TestWindowClass", NULL, WS_OVERLAPPEDWINDOW , CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0, NULL, NULL, 0);
info.id = SetTimer(info.hWnd,TIMER_ID,10000,tfunc); ok(info.id, "SetTimer failed\n"); ok(info.id==TIMER_ID, "SetTimer timer ID different\n"); info.handles[0] = CreateEventW(NULL,0,0,NULL); info.handles[1] = CreateThread(NULL,0,timer_thread_proc,&info,0,&id);
WaitForMultipleObjects(2, info.handles, FALSE, INFINITE);
WaitForSingleObject(info.handles[1], INFINITE);
CloseHandle(info.handles[0]); CloseHandle(info.handles[1]);
ok( KillTimer(info.hWnd, TIMER_ID), "KillTimer failed\n");
/* Check the minimum allowed timeout for a timer. MSDN indicates that it should be 10.0 ms, * which occurs sometimes, but most testing on the VMs indicates a minimum timeout closer to * 15.6 ms. Since there is some measurement error between test runs we are allowing for * ±9 counts (~4 ms) around the expected value. */ count = 0; id = SetTimer(info.hWnd, TIMER_ID, 0, callback_count); ok(id != 0, "did not get id from SetTimer.\n"); ok(id==TIMER_ID, "SetTimer timer ID different\n"); start = GetTickCount(); while (GetTickCount()-start < 1001 && GetMessageA(&msg, info.hWnd, 0, 0)) DispatchMessageA(&msg);ros_skip_flakytodo_wine ok(abs(count-TIMER_COUNT_EXPECTED) < TIMER_COUNT_TOLERANCE /* xp */ || broken(abs(count-64) < TIMER_COUNT_TOLERANCE) /* most common */ || broken(abs(count-43) < TIMER_COUNT_TOLERANCE) /* w2k3, win8 */, "did not get expected count for minimum timeout (%d != ~%d).\n", count, TIMER_COUNT_EXPECTED); ok(KillTimer(info.hWnd, id), "KillTimer failed\n"); /* Perform the same check on SetSystemTimer (only available on w2k3 and older) */ if (pSetSystemTimer) { int syscount = 0;
count = 0; id = pSetSystemTimer(info.hWnd, TIMER_ID, 0, callback_count); ok(id != 0, "did not get id from SetSystemTimer.\n"); ok(id==TIMER_ID, "SetTimer timer ID different\n"); start = GetTickCount(); while (GetTickCount()-start < 1001 && GetMessageA(&msg, info.hWnd, 0, 0)) { if (msg.message == WM_SYSTIMER) syscount++; DispatchMessageA(&msg); } ok(abs(syscount-TIMER_COUNT_EXPECTED) < TIMER_COUNT_TOLERANCE || broken(abs(syscount-64) < TIMER_COUNT_TOLERANCE) /* most common */ || broken(syscount > 4000 && syscount < 12000) /* win2k3sp0 */, "did not get expected count for minimum timeout (%d != ~%d).\n", syscount, TIMER_COUNT_EXPECTED); todo_wine ok(count == 0, "did not get expected count for callback timeout (%d != 0).\n", count); ok(pKillSystemTimer(info.hWnd, id), "KillSystemTimer failed\n"); }
ok(DestroyWindow(info.hWnd), "failed to destroy window\n");}
static void test_timers_no_wnd(void){ static UINT_PTR ids[0xffff]; UINT_PTR id, id2; DWORD start; MSG msg; int i;
count = 0; id = SetTimer(NULL, 0, 100, callback_count); ok(id != 0, "did not get id from SetTimer.\n"); id2 = SetTimer(NULL, id, 200, callback_count); ok(id2 == id, "did not get same id from SetTimer when replacing (%li expected %li).\n", id2, id); Sleep(150); while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok(count == 0, "did not get zero count as expected (%i).\n", count); Sleep(150); while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok(count == 1, "did not get one count as expected (%i).\n", count); KillTimer(NULL, id); Sleep(250); while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok(count == 1, "killing replaced timer did not work (%i).\n", count);
/* Check the minimum allowed timeout for a timer. MSDN indicates that it should be 10.0 ms, * which occurs sometimes, but most testing on the VMs indicates a minimum timeout closer to * 15.6 ms. Since there is some measurement error between test runs we are allowing for * ±9 counts (~4 ms) around the expected value. */ count = 0; id = SetTimer(NULL, 0, 0, callback_count); ok(id != 0, "did not get id from SetTimer.\n"); start = GetTickCount(); while (GetTickCount()-start < 1001 && GetMessageA(&msg, NULL, 0, 0)) DispatchMessageA(&msg);todo_wine ok(abs(count-TIMER_COUNT_EXPECTED) < TIMER_COUNT_TOLERANCE /* xp */ || broken(abs(count-64) < TIMER_COUNT_TOLERANCE) /* most common */, "did not get expected count for minimum timeout (%d != ~%d).\n", count, TIMER_COUNT_EXPECTED); KillTimer(NULL, id); /* Note: SetSystemTimer doesn't support a NULL window, see test_timers */
if (pSetCoalescableTimer) { count = 0; id = pSetCoalescableTimer(NULL, 0, 0, callback_count, 0); ok(id != 0, "SetCoalescableTimer failed with %u.\n", GetLastError()); start = GetTickCount(); while (GetTickCount()-start < 100 && GetMessageA(&msg, NULL, 0, 0)) DispatchMessageA(&msg); ok(count > 1, "expected count > 1, got %d.\n", count); KillTimer(NULL, id); } else win_skip("SetCoalescableTimer not available.\n");
/* Check what happens when we're running out of timers */ for (i = 0; i < ARRAY_SIZE(ids); i++) { SetLastError(0xdeadbeef); ids[i] = SetTimer(NULL, 0, USER_TIMER_MAXIMUM, tfunc); if (!ids[i]) break; } ok(i != ARRAY_SIZE(ids), "all timers were created successfully\n"); ok(GetLastError()==ERROR_NO_MORE_USER_HANDLES || broken(GetLastError()==0xdeadbeef), "GetLastError() = %d\n", GetLastError()); while (i > 0) KillTimer(NULL, ids[--i]);}
static void test_timers_exception(DWORD code){ UINT_PTR id; MSG msg;
exception = code; id = SetTimer(NULL, 0, 1000, callback_exception); ok(id != 0, "did not get id from SetTimer.\n");
memset(&msg, 0, sizeof(msg)); msg.message = WM_TIMER; msg.wParam = id; msg.lParam = (LPARAM)callback_exception;
count = 0; DispatchMessageA(&msg); ok(count == 1, "did not get one count as expected (%i).\n", count);
KillTimer(NULL, id);}
static void test_timers_exceptions(void){ test_timers_exception(EXCEPTION_ACCESS_VIOLATION); test_timers_exception(EXCEPTION_DATATYPE_MISALIGNMENT); test_timers_exception(EXCEPTION_BREAKPOINT); test_timers_exception(EXCEPTION_SINGLE_STEP); test_timers_exception(EXCEPTION_ARRAY_BOUNDS_EXCEEDED); test_timers_exception(EXCEPTION_FLT_DENORMAL_OPERAND); test_timers_exception(EXCEPTION_FLT_DIVIDE_BY_ZERO); test_timers_exception(EXCEPTION_FLT_INEXACT_RESULT); test_timers_exception(EXCEPTION_ILLEGAL_INSTRUCTION); test_timers_exception(0xE000BEEF); /* customer exception */}
/* Various win events with arbitrary parameters */static const struct message WmWinEventsSeq[] = { { EVENT_SYSTEM_SOUND, winevent_hook|wparam|lparam, OBJID_WINDOW, 0 }, { EVENT_SYSTEM_ALERT, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 }, { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, OBJID_TITLEBAR, 2 }, { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_MENU, 3 }, { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam, OBJID_CLIENT, 4 }, { EVENT_SYSTEM_MENUPOPUPSTART, winevent_hook|wparam|lparam, OBJID_VSCROLL, 5 }, { EVENT_SYSTEM_MENUPOPUPEND, winevent_hook|wparam|lparam, OBJID_HSCROLL, 6 }, { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, OBJID_SIZEGRIP, 7 }, { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, OBJID_CARET, 8 }, /* our win event hook ignores OBJID_CURSOR events */ /*{ EVENT_SYSTEM_MOVESIZESTART, winevent_hook|wparam|lparam, OBJID_CURSOR, 9 },*/ { EVENT_SYSTEM_MOVESIZEEND, winevent_hook|wparam|lparam, OBJID_ALERT, 10 }, { EVENT_SYSTEM_CONTEXTHELPSTART, winevent_hook|wparam|lparam, OBJID_SOUND, 11 }, { EVENT_SYSTEM_CONTEXTHELPEND, winevent_hook|wparam|lparam, OBJID_QUERYCLASSNAMEIDX, 12 }, { EVENT_SYSTEM_DRAGDROPSTART, winevent_hook|wparam|lparam, OBJID_NATIVEOM, 13 }, { EVENT_SYSTEM_DRAGDROPEND, winevent_hook|wparam|lparam, OBJID_WINDOW, 0 }, { EVENT_SYSTEM_DIALOGSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 }, { EVENT_SYSTEM_DIALOGEND, winevent_hook|wparam|lparam, OBJID_TITLEBAR, 2 }, { EVENT_SYSTEM_SCROLLINGSTART, winevent_hook|wparam|lparam, OBJID_MENU, 3 }, { EVENT_SYSTEM_SCROLLINGEND, winevent_hook|wparam|lparam, OBJID_CLIENT, 4 }, { EVENT_SYSTEM_SWITCHSTART, winevent_hook|wparam|lparam, OBJID_VSCROLL, 5 }, { EVENT_SYSTEM_SWITCHEND, winevent_hook|wparam|lparam, OBJID_HSCROLL, 6 }, { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, OBJID_SIZEGRIP, 7 }, { EVENT_SYSTEM_MINIMIZEEND, winevent_hook|wparam|lparam, OBJID_CARET, 8 }, { 0 }};static const struct message WmWinEventCaretSeq[] = { { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1 */ { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1 */ { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 2 */ { EVENT_OBJECT_NAMECHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1 */ { 0 }};static const struct message WmWinEventCaretSeq_2[] = { { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1/2 */ { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1/2 */ { EVENT_OBJECT_NAMECHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1/2 */ { 0 }};static const struct message WmWinEventAlertSeq[] = { { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_ALERT, 0 }, { 0 }};static const struct message WmWinEventAlertSeq_2[] = { /* create window in the thread proc */ { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_WINDOW, 2 }, /* our test event */ { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_ALERT, 2 }, { 0 }};static const struct message WmGlobalHookSeq_1[] = { /* create window in the thread proc */ { HCBT_CREATEWND, hook|lparam, 0, 2 }, /* our test events */ { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_PREVWINDOW, 2 }, { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_NEXTWINDOW, 2 }, { 0 }};static const struct message WmGlobalHookSeq_2[] = { { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_NEXTWINDOW, 0 }, /* old local hook */ { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_NEXTWINDOW, 2 }, /* new global hook */ { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_PREVWINDOW, 0 }, /* old local hook */ { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_PREVWINDOW, 2 }, /* new global hook */ { 0 }};
static const struct message WmMouseLLHookSeq[] = { { WM_MOUSEMOVE, hook }, { WM_LBUTTONUP, hook }, { WM_MOUSEMOVE, hook }, { 0 }};
static void CALLBACK win_event_global_hook_proc(HWINEVENTHOOK hevent, DWORD event, HWND hwnd, LONG object_id, LONG child_id, DWORD thread_id, DWORD event_time){ char buf[256];
if (GetClassNameA(hwnd, buf, sizeof(buf))) { if (!lstrcmpiA(buf, "TestWindowClass") || !lstrcmpiA(buf, "static")) { struct recvd_message msg;
msg.hwnd = hwnd; msg.message = event; msg.flags = winevent_hook|wparam|lparam; msg.wParam = object_id; msg.lParam = (thread_id == GetCurrentThreadId()) ? child_id : (child_id + 2); msg.descr = "WEH_2"; add_message(&msg); } }}
static HHOOK hCBT_global_hook;static DWORD cbt_global_hook_thread_id;
static LRESULT CALLBACK cbt_global_hook_proc(int nCode, WPARAM wParam, LPARAM lParam) { HWND hwnd; char buf[256];
if (nCode == HCBT_SYSCOMMAND) { struct recvd_message msg;
msg.hwnd = 0; msg.message = nCode; msg.flags = hook|wparam|lparam; msg.wParam = wParam; msg.lParam = (cbt_global_hook_thread_id == GetCurrentThreadId()) ? 1 : 2; msg.descr = "CBT_2"; add_message(&msg);
return CallNextHookEx(hCBT_global_hook, nCode, wParam, lParam); } /* WH_MOUSE_LL hook */ if (nCode == HC_ACTION) { MSLLHOOKSTRUCT *mhll = (MSLLHOOKSTRUCT *)lParam;
/* we can't test for real mouse events */ if (mhll->flags & LLMHF_INJECTED) { struct recvd_message msg;
memset (&msg, 0, sizeof (msg)); msg.message = wParam; msg.flags = hook; msg.descr = "CBT_2"; add_message(&msg); } return CallNextHookEx(hCBT_global_hook, nCode, wParam, lParam); }
/* Log also SetFocus(0) calls */ hwnd = wParam ? (HWND)wParam : (HWND)lParam;
if (GetClassNameA(hwnd, buf, sizeof(buf))) { if (!lstrcmpiA(buf, "TestWindowClass") || !lstrcmpiA(buf, "static")) { struct recvd_message msg;
msg.hwnd = hwnd; msg.message = nCode; msg.flags = hook|wparam|lparam; msg.wParam = wParam; msg.lParam = (cbt_global_hook_thread_id == GetCurrentThreadId()) ? 1 : 2; msg.descr = "CBT_2"; add_message(&msg); } } return CallNextHookEx(hCBT_global_hook, nCode, wParam, lParam);}
static DWORD WINAPI win_event_global_thread_proc(void *param){ HWND hwnd; MSG msg; HANDLE hevent = *(HANDLE *)param;
assert(pNotifyWinEvent);
hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL); assert(hwnd); trace("created thread window %p\n", hwnd);
*(HWND *)param = hwnd;
flush_sequence(); /* this event should be received only by our new hook proc, * an old one does not expect an event from another thread. */ pNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE, hwnd, OBJID_ALERT, 0); SetEvent(hevent);
while (GetMessageA(&msg, 0, 0, 0)) { TranslateMessage(&msg); DispatchMessageA(&msg); } return 0;}
static DWORD WINAPI cbt_global_hook_thread_proc(void *param){ HWND hwnd; MSG msg; HANDLE hevent = *(HANDLE *)param;
flush_sequence(); /* these events should be received only by our new hook proc, * an old one does not expect an event from another thread. */
hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL); assert(hwnd); trace("created thread window %p\n", hwnd);
*(HWND *)param = hwnd;
/* Windows doesn't like when a thread plays games with the focus, that leads to all kinds of misbehaviours and failures to activate a window. So, better keep next lines commented out. SetFocus(0); SetFocus(hwnd);*/
DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_PREVWINDOW, 0); DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_NEXTWINDOW, 0);
SetEvent(hevent);
while (GetMessageA(&msg, 0, 0, 0)) { TranslateMessage(&msg); DispatchMessageA(&msg); } return 0;}
static DWORD WINAPI mouse_ll_global_thread_proc(void *param){ HWND hwnd; MSG msg; HANDLE hevent = *(HANDLE *)param;
hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL); assert(hwnd); trace("created thread window %p\n", hwnd);
*(HWND *)param = hwnd;
flush_sequence();
/* Windows doesn't like when a thread plays games with the focus, * that leads to all kinds of misbehaviours and failures to activate * a window. So, better don't generate a mouse click message below. */ mouse_event(MOUSEEVENTF_MOVE, -1, 0, 0, 0); mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); mouse_event(MOUSEEVENTF_MOVE, 1, 0, 0, 0);
SetEvent(hevent); while (GetMessageA(&msg, 0, 0, 0)) { TranslateMessage(&msg); DispatchMessageA(&msg); } return 0;}
static void test_winevents(void){ BOOL ret; MSG msg; HWND hwnd, hwnd2; UINT i; HANDLE hthread, hevent; DWORD tid; HWINEVENTHOOK hhook; const struct message *events = WmWinEventsSeq;
hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0, NULL, NULL, 0); assert(hwnd);
/****** start of global hook test *************/ hCBT_global_hook = SetWindowsHookExA(WH_CBT, cbt_global_hook_proc, GetModuleHandleA(0), 0); if (!hCBT_global_hook) { ok(DestroyWindow(hwnd), "failed to destroy window\n"); skip( "cannot set global hook\n" ); return; }
hevent = CreateEventA(NULL, 0, 0, NULL); assert(hevent); hwnd2 = hevent;
hthread = CreateThread(NULL, 0, cbt_global_hook_thread_proc, &hwnd2, 0, &tid); ok(hthread != NULL, "CreateThread failed, error %d\n", GetLastError());
ok(WaitForSingleObject(hevent, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
ok_sequence(WmGlobalHookSeq_1, "global hook 1", FALSE);
flush_sequence(); /* this one should be received only by old hook proc */ DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_NEXTWINDOW, 0); /* this one should be received only by old hook proc */ DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_PREVWINDOW, 0);
ok_sequence(WmGlobalHookSeq_2, "global hook 2", FALSE);
ret = UnhookWindowsHookEx(hCBT_global_hook); ok( ret, "UnhookWindowsHookEx error %d\n", GetLastError());
PostThreadMessageA(tid, WM_QUIT, 0, 0); ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); CloseHandle(hthread); CloseHandle(hevent); ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n"); /****** end of global hook test *************/
if (!pSetWinEventHook || !pNotifyWinEvent || !pUnhookWinEvent) { ok(DestroyWindow(hwnd), "failed to destroy window\n"); return; }
flush_sequence();
if (0) { /* this test doesn't pass under Win9x */ /* win2k ignores events with hwnd == 0 */ SetLastError(0xdeadbeef); pNotifyWinEvent(events[0].message, 0, events[0].wParam, events[0].lParam); ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || /* Win2k */ GetLastError() == 0xdeadbeef, /* Win9x */ "unexpected error %d\n", GetLastError()); ok_sequence(WmEmptySeq, "empty notify winevents", FALSE); }
for (i = 0; i < ARRAY_SIZE(WmWinEventsSeq); i++) pNotifyWinEvent(events[i].message, hwnd, events[i].wParam, events[i].lParam);
ok_sequence(WmWinEventsSeq, "notify winevents", FALSE);
/****** start of event filtering test *************/ hhook = pSetWinEventHook( EVENT_OBJECT_SHOW, /* 0x8002 */ EVENT_OBJECT_LOCATIONCHANGE, /* 0x800B */ GetModuleHandleA(0), win_event_global_hook_proc, GetCurrentProcessId(), 0, WINEVENT_INCONTEXT); ok(hhook != 0, "SetWinEventHook error %d\n", GetLastError());
hevent = CreateEventA(NULL, 0, 0, NULL); assert(hevent); hwnd2 = hevent;
hthread = CreateThread(NULL, 0, win_event_global_thread_proc, &hwnd2, 0, &tid); ok(hthread != NULL, "CreateThread failed, error %d\n", GetLastError());
ok(WaitForSingleObject(hevent, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
ok_sequence(WmWinEventAlertSeq, "alert winevent", FALSE);
flush_sequence(); /* this one should be received only by old hook proc */ pNotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_CARET, 0); /* 0x8000 */ pNotifyWinEvent(EVENT_OBJECT_SHOW, hwnd, OBJID_CARET, 0); /* 0x8002 */ /* this one should be received only by old hook proc */ pNotifyWinEvent(EVENT_OBJECT_NAMECHANGE, hwnd, OBJID_CARET, 0); /* 0x800C */
ok_sequence(WmWinEventCaretSeq, "caret winevent", FALSE);
ret = pUnhookWinEvent(hhook); ok( ret, "UnhookWinEvent error %d\n", GetLastError());
PostThreadMessageA(tid, WM_QUIT, 0, 0); ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); CloseHandle(hthread); CloseHandle(hevent); ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n"); /****** end of event filtering test *************/
/****** start of out of context event test *************/ hhook = pSetWinEventHook(EVENT_MIN, EVENT_MAX, 0, win_event_global_hook_proc, GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT); ok(hhook != 0, "SetWinEventHook error %d\n", GetLastError());
hevent = CreateEventA(NULL, 0, 0, NULL); assert(hevent); hwnd2 = hevent;
flush_sequence();
hthread = CreateThread(NULL, 0, win_event_global_thread_proc, &hwnd2, 0, &tid); ok(hthread != NULL, "CreateThread failed, error %d\n", GetLastError());
ok(WaitForSingleObject(hevent, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
ok_sequence(WmEmptySeq, "empty notify winevents", FALSE); /* process pending winevent messages */ ok(!PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE), "msg queue should be empty\n"); ok_sequence(WmWinEventAlertSeq_2, "alert winevent for out of context proc", FALSE);
flush_sequence(); /* this one should be received only by old hook proc */ pNotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_CARET, 0); /* 0x8000 */ pNotifyWinEvent(EVENT_OBJECT_SHOW, hwnd, OBJID_CARET, 0); /* 0x8002 */ /* this one should be received only by old hook proc */ pNotifyWinEvent(EVENT_OBJECT_NAMECHANGE, hwnd, OBJID_CARET, 0); /* 0x800C */
ok_sequence(WmWinEventCaretSeq_2, "caret winevent for incontext proc", FALSE); /* process pending winevent messages */ ok(!PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE), "msg queue should be empty\n"); ok_sequence(WmWinEventCaretSeq_2, "caret winevent for out of context proc", FALSE);
ret = pUnhookWinEvent(hhook); ok( ret, "UnhookWinEvent error %d\n", GetLastError());
PostThreadMessageA(tid, WM_QUIT, 0, 0); ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); CloseHandle(hthread); CloseHandle(hevent); ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n"); /****** end of out of context event test *************/
/****** start of MOUSE_LL hook test *************/ hCBT_global_hook = SetWindowsHookExA(WH_MOUSE_LL, cbt_global_hook_proc, GetModuleHandleA(0), 0); /* WH_MOUSE_LL is not supported on Win9x platforms */ if (!hCBT_global_hook) { win_skip("Skipping WH_MOUSE_LL test on this platform\n"); goto skip_mouse_ll_hook_test; }
hevent = CreateEventA(NULL, 0, 0, NULL); assert(hevent); hwnd2 = hevent;
hthread = CreateThread(NULL, 0, mouse_ll_global_thread_proc, &hwnd2, 0, &tid); ok(hthread != NULL, "CreateThread failed, error %d\n", GetLastError());
while (WaitForSingleObject(hevent, 100) == WAIT_TIMEOUT) while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
ok_sequence(WmMouseLLHookSeq, "MOUSE_LL hook other thread", FALSE); flush_sequence();
mouse_event(MOUSEEVENTF_MOVE, -1, 0, 0, 0); mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); mouse_event(MOUSEEVENTF_MOVE, 1, 0, 0, 0);
ok_sequence(WmMouseLLHookSeq, "MOUSE_LL hook same thread", FALSE);
ret = UnhookWindowsHookEx(hCBT_global_hook); ok( ret, "UnhookWindowsHookEx error %d\n", GetLastError());
PostThreadMessageA(tid, WM_QUIT, 0, 0); ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); CloseHandle(hthread); CloseHandle(hevent); ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n"); /****** end of MOUSE_LL hook test *************/skip_mouse_ll_hook_test:
ok(DestroyWindow(hwnd), "failed to destroy window\n");}
static void test_set_hook(void){ BOOL ret; HHOOK hhook; HWINEVENTHOOK hwinevent_hook;
hhook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, GetModuleHandleA(0), GetCurrentThreadId()); ok(hhook != 0, "local hook does not require hModule set to 0\n"); UnhookWindowsHookEx(hhook);
if (0) { /* this test doesn't pass under Win9x: BUG! */ SetLastError(0xdeadbeef); hhook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, 0); ok(!hhook, "global hook requires hModule != 0\n"); ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD, "unexpected error %d\n", GetLastError()); }
SetLastError(0xdeadbeef); hhook = SetWindowsHookExA(WH_CBT, 0, GetModuleHandleA(0), GetCurrentThreadId()); ok(!hhook, "SetWinEventHook with invalid proc should fail\n"); ok(GetLastError() == ERROR_INVALID_FILTER_PROC || /* Win2k */ GetLastError() == 0xdeadbeef, /* Win9x */ "unexpected error %d\n", GetLastError());
SetLastError(0xdeadbeef); ok(!UnhookWindowsHookEx((HHOOK)0xdeadbeef), "UnhookWindowsHookEx succeeded\n"); ok(GetLastError() == ERROR_INVALID_HOOK_HANDLE || /* Win2k */ GetLastError() == 0xdeadbeef, /* Win9x */ "unexpected error %d\n", GetLastError());
if (!pSetWinEventHook || !pUnhookWinEvent) return;
/* even process local incontext hooks require hmodule */ SetLastError(0xdeadbeef); hwinevent_hook = pSetWinEventHook(EVENT_MIN, EVENT_MAX, 0, win_event_proc, GetCurrentProcessId(), 0, WINEVENT_INCONTEXT); ok(!hwinevent_hook, "WINEVENT_INCONTEXT requires hModule != 0\n"); ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD || /* Win2k */ GetLastError() == 0xdeadbeef, /* Win9x */ "unexpected error %d\n", GetLastError());
/* even thread local incontext hooks require hmodule */ SetLastError(0xdeadbeef); hwinevent_hook = pSetWinEventHook(EVENT_MIN, EVENT_MAX, 0, win_event_proc, GetCurrentProcessId(), GetCurrentThreadId(), WINEVENT_INCONTEXT); ok(!hwinevent_hook, "WINEVENT_INCONTEXT requires hModule != 0\n"); ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD || /* Win2k */ GetLastError() == 0xdeadbeef, /* Win9x */ "unexpected error %d\n", GetLastError());
if (0) { /* these 3 tests don't pass under Win9x */ SetLastError(0xdeadbeef); hwinevent_hook = pSetWinEventHook(1, 0, 0, win_event_proc, GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT); ok(!hwinevent_hook, "SetWinEventHook with invalid event range should fail\n"); ok(GetLastError() == ERROR_INVALID_HOOK_FILTER, "unexpected error %d\n", GetLastError());
SetLastError(0xdeadbeef); hwinevent_hook = pSetWinEventHook(-1, 1, 0, win_event_proc, GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT); ok(!hwinevent_hook, "SetWinEventHook with invalid event range should fail\n"); ok(GetLastError() == ERROR_INVALID_HOOK_FILTER, "unexpected error %d\n", GetLastError());
SetLastError(0xdeadbeef); hwinevent_hook = pSetWinEventHook(EVENT_MIN, EVENT_MAX, 0, win_event_proc, 0, 0xdeadbeef, WINEVENT_OUTOFCONTEXT); ok(!hwinevent_hook, "SetWinEventHook with invalid tid should fail\n"); ok(GetLastError() == ERROR_INVALID_THREAD_ID, "unexpected error %d\n", GetLastError()); }
SetLastError(0xdeadbeef); hwinevent_hook = pSetWinEventHook(0, 0, 0, win_event_proc, GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT); ok(hwinevent_hook != 0, "SetWinEventHook error %d\n", GetLastError()); ok(GetLastError() == 0xdeadbeef, "unexpected error %d\n", GetLastError()); ret = pUnhookWinEvent(hwinevent_hook); ok( ret, "UnhookWinEvent error %d\n", GetLastError());
todo_wine { /* This call succeeds under win2k SP4, but fails under Wine. Does win2k test/use passed process id? */ SetLastError(0xdeadbeef); hwinevent_hook = pSetWinEventHook(EVENT_MIN, EVENT_MAX, 0, win_event_proc, 0xdeadbeef, 0, WINEVENT_OUTOFCONTEXT); ok(hwinevent_hook != 0, "SetWinEventHook error %d\n", GetLastError()); ok(GetLastError() == 0xdeadbeef, "unexpected error %d\n", GetLastError()); ret = pUnhookWinEvent(hwinevent_hook); ok( ret, "UnhookWinEvent error %d\n", GetLastError());}
SetLastError(0xdeadbeef); ok(!pUnhookWinEvent((HWINEVENTHOOK)0xdeadbeef), "UnhookWinEvent succeeded\n"); ok(GetLastError() == ERROR_INVALID_HANDLE || /* Win2k */ GetLastError() == 0xdeadbeef, /* Win9x */ "unexpected error %d\n", GetLastError());}
static HWND hook_hwnd;static HHOOK recursive_hook;static int hook_depth, max_hook_depth;
static LRESULT WINAPI rec_get_message_hook(int code, WPARAM w, LPARAM l){ LRESULT res; MSG msg; BOOL b;
hook_depth++; if(hook_depth > max_hook_depth) max_hook_depth = hook_depth;
b = PeekMessageW(&msg, hook_hwnd, 0, 0, PM_NOREMOVE); ok(b, "PeekMessage failed\n");
res = CallNextHookEx(recursive_hook, code, w, l);
hook_depth--; return res;}
static void test_recursive_hook(void){ MSG msg; BOOL b;
hook_hwnd = CreateWindowA("Static", NULL, WS_POPUP, 0, 0, 200, 60, NULL, NULL, NULL, NULL); ok(hook_hwnd != NULL, "CreateWindow failed\n");
recursive_hook = SetWindowsHookExW(WH_GETMESSAGE, rec_get_message_hook, NULL, GetCurrentThreadId()); ok(recursive_hook != NULL, "SetWindowsHookEx failed\n");
PostMessageW(hook_hwnd, WM_USER, 0, 0); PostMessageW(hook_hwnd, WM_USER+1, 0, 0);
hook_depth = 0; GetMessageW(&msg, hook_hwnd, 0, 0); ok(15 <= max_hook_depth && max_hook_depth < 45, "max_hook_depth = %d\n", max_hook_depth); trace("max_hook_depth = %d\n", max_hook_depth);
b = UnhookWindowsHookEx(recursive_hook); ok(b, "UnhokWindowsHookEx failed\n");
DestroyWindow(hook_hwnd);}
static const struct message ScrollWindowPaint1[] = { { WM_PAINT, sent }, { WM_ERASEBKGND, sent|beginpaint }, { WM_GETTEXTLENGTH, sent|optional }, { WM_PAINT, sent|optional }, { WM_NCPAINT, sent|beginpaint|optional }, { WM_GETTEXT, sent|beginpaint|optional }, { WM_GETTEXT, sent|beginpaint|optional }, { WM_GETTEXT, sent|beginpaint|optional }, { WM_GETTEXT, sent|beginpaint|defwinproc|optional }, { WM_ERASEBKGND, sent|beginpaint|optional }, { 0 }};
static const struct message ScrollWindowPaint2[] = { { WM_PAINT, sent }, { 0 }};
static void test_scrollwindowex(void){ HWND hwnd, hchild; RECT rect={0,0,130,130};
hwnd = CreateWindowExA(0, "TestWindowClass", "Test Scroll", WS_VISIBLE|WS_OVERLAPPEDWINDOW, 100, 100, 200, 200, 0, 0, 0, NULL); ok (hwnd != 0, "Failed to create overlapped window\n"); hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_VISIBLE|WS_CAPTION|WS_CHILD, 10, 10, 150, 150, hwnd, 0, 0, NULL); ok (hchild != 0, "Failed to create child\n"); UpdateWindow(hwnd); flush_events(); flush_sequence();
/* scroll without the child window */ trace("start scroll\n"); ScrollWindowEx( hwnd, 10, 10, &rect, NULL, NULL, NULL, SW_ERASE|SW_INVALIDATE); ok_sequence(WmEmptySeq, "ScrollWindowEx", FALSE); trace("end scroll\n"); flush_sequence(); flush_events(); ok_sequence(ScrollWindowPaint1, "ScrollWindowEx", FALSE); flush_events(); flush_sequence();
/* Now without the SW_ERASE flag */ trace("start scroll\n"); ScrollWindowEx( hwnd, 10, 10, &rect, NULL, NULL, NULL, SW_INVALIDATE); ok_sequence(WmEmptySeq, "ScrollWindowEx", FALSE); trace("end scroll\n"); flush_sequence(); flush_events(); ok_sequence(ScrollWindowPaint2, "ScrollWindowEx", FALSE); flush_events(); flush_sequence();
/* now scroll the child window as well */ trace("start scroll\n"); ScrollWindowEx( hwnd, 10, 10, &rect, NULL, NULL, NULL, SW_SCROLLCHILDREN|SW_ERASE|SW_INVALIDATE); /* wine sends WM_POSCHANGING, WM_POSCHANGED messages */ /* windows sometimes a WM_MOVE */ ok_sequence(WmEmptySeq, "ScrollWindowEx", TRUE); trace("end scroll\n"); flush_sequence(); flush_events(); ok_sequence(ScrollWindowPaint1, "ScrollWindowEx", FALSE); flush_events(); flush_sequence();
/* now scroll with ScrollWindow() */ trace("start scroll with ScrollWindow\n"); ScrollWindow( hwnd, 5, 5, NULL, NULL); trace("end scroll\n"); flush_sequence(); flush_events(); ok_sequence(ScrollWindowPaint1, "ScrollWindow", FALSE);
ok(DestroyWindow(hchild), "failed to destroy window\n"); ok(DestroyWindow(hwnd), "failed to destroy window\n"); flush_sequence();}
static const struct message destroy_window_with_children[] = { { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, /* popup */ { HCBT_DESTROYWND, hook|lparam, 0, WND_PARENT_ID }, /* parent */ { 0x0090, sent|optional }, { HCBT_DESTROYWND, hook|lparam, 0, WND_POPUP_ID }, /* popup */ { 0x0090, sent|optional }, { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, /* popup */ { WM_DESTROY, sent|wparam|lparam, 0, WND_POPUP_ID }, /* popup */ { WM_CAPTURECHANGED, sent|wparam|lparam, 0, WND_POPUP_ID }, /* popup */ { WM_NCDESTROY, sent|wparam|lparam, 0, WND_POPUP_ID }, /* popup */ { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, /* parent */ { WM_DESTROY, sent|wparam|lparam, 0, WND_PARENT_ID }, /* parent */ { WM_DESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 2 }, /* child2 */ { WM_DESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 1 }, /* child1 */ { WM_DESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 3 }, /* child3 */ { WM_NCDESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 2 }, /* child2 */ { WM_NCDESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 3 }, /* child3 */ { WM_NCDESTROY, sent|wparam|lparam, 0, WND_CHILD_ID + 1 }, /* child1 */ { WM_NCDESTROY, sent|wparam|lparam, 0, WND_PARENT_ID }, /* parent */ { 0 }};
static void test_DestroyWindow(void){ BOOL ret; HWND parent, child1, child2, child3, child4, test; UINT_PTR child_id = WND_CHILD_ID + 1;
parent = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW, 100, 100, 200, 200, 0, 0, 0, NULL); assert(parent != 0); child1 = CreateWindowExA(0, "TestWindowClass", NULL, WS_CHILD, 0, 0, 50, 50, parent, (HMENU)child_id++, 0, NULL); assert(child1 != 0); child2 = CreateWindowExA(0, "TestWindowClass", NULL, WS_CHILD, 0, 0, 50, 50, GetDesktopWindow(), (HMENU)child_id++, 0, NULL); assert(child2 != 0); child3 = CreateWindowExA(0, "TestWindowClass", NULL, WS_CHILD, 0, 0, 50, 50, child1, (HMENU)child_id++, 0, NULL); assert(child3 != 0); child4 = CreateWindowExA(0, "TestWindowClass", NULL, WS_POPUP, 0, 0, 50, 50, parent, 0, 0, NULL); assert(child4 != 0);
/* test owner/parent of child2 */ test = GetParent(child2); ok(test == GetDesktopWindow(), "wrong parent %p\n", test); ok(!IsChild(parent, child2), "wrong parent/child %p/%p\n", parent, child2); if(pGetAncestor) { test = pGetAncestor(child2, GA_PARENT); ok(test == GetDesktopWindow(), "wrong parent %p\n", test); } test = GetWindow(child2, GW_OWNER); ok(!test, "wrong owner %p\n", test);
test = SetParent(child2, parent); ok(test == GetDesktopWindow(), "wrong old parent %p\n", test);
/* test owner/parent of the parent */ test = GetParent(parent); ok(!test, "wrong parent %p\n", test); ok(!IsChild(GetDesktopWindow(), parent), "wrong parent/child %p/%p\n", GetDesktopWindow(), parent); if(pGetAncestor) { test = pGetAncestor(parent, GA_PARENT); ok(test == GetDesktopWindow(), "wrong parent %p\n", test); } test = GetWindow(parent, GW_OWNER); ok(!test, "wrong owner %p\n", test);
/* test owner/parent of child1 */ test = GetParent(child1); ok(test == parent, "wrong parent %p\n", test); ok(IsChild(parent, child1), "wrong parent/child %p/%p\n", parent, child1); if(pGetAncestor) { test = pGetAncestor(child1, GA_PARENT); ok(test == parent, "wrong parent %p\n", test); } test = GetWindow(child1, GW_OWNER); ok(!test, "wrong owner %p\n", test);
/* test owner/parent of child2 */ test = GetParent(child2); ok(test == parent, "wrong parent %p\n", test); ok(IsChild(parent, child2), "wrong parent/child %p/%p\n", parent, child2); if(pGetAncestor) { test = pGetAncestor(child2, GA_PARENT); ok(test == parent, "wrong parent %p\n", test); } test = GetWindow(child2, GW_OWNER); ok(!test, "wrong owner %p\n", test);
/* test owner/parent of child3 */ test = GetParent(child3); ok(test == child1, "wrong parent %p\n", test); ok(IsChild(parent, child3), "wrong parent/child %p/%p\n", parent, child3); if(pGetAncestor) { test = pGetAncestor(child3, GA_PARENT); ok(test == child1, "wrong parent %p\n", test); } test = GetWindow(child3, GW_OWNER); ok(!test, "wrong owner %p\n", test);
/* test owner/parent of child4 */ test = GetParent(child4); ok(test == parent, "wrong parent %p\n", test); ok(!IsChild(parent, child4), "wrong parent/child %p/%p\n", parent, child4); if(pGetAncestor) { test = pGetAncestor(child4, GA_PARENT); ok(test == GetDesktopWindow(), "wrong parent %p\n", test); } test = GetWindow(child4, GW_OWNER); ok(test == parent, "wrong owner %p\n", test);
flush_sequence();
trace("parent %p, child1 %p, child2 %p, child3 %p, child4 %p\n", parent, child1, child2, child3, child4);
SetCapture(child4); test = GetCapture(); ok(test == child4, "wrong capture window %p\n", test);
test_DestroyWindow_flag = TRUE; ret = DestroyWindow(parent); ok( ret, "DestroyWindow() error %d\n", GetLastError()); test_DestroyWindow_flag = FALSE; ok_sequence(destroy_window_with_children, "destroy window with children", FALSE);
ok(!IsWindow(parent), "parent still exists\n"); ok(!IsWindow(child1), "child1 still exists\n"); ok(!IsWindow(child2), "child2 still exists\n"); ok(!IsWindow(child3), "child3 still exists\n"); ok(!IsWindow(child4), "child4 still exists\n");
test = GetCapture(); ok(!test, "wrong capture window %p\n", test);}
static const struct message WmDispatchPaint[] = { { WM_NCPAINT, sent }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent }, { 0 }};
static LRESULT WINAPI DispatchMessageCheckProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ if (message == WM_PAINT) return 0; return MsgCheckProcA( hwnd, message, wParam, lParam );}
static void test_DispatchMessage(void){ RECT rect; MSG msg; int count; HWND hwnd = CreateWindowA( "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW, 100, 100, 200, 200, 0, 0, 0, NULL); ShowWindow( hwnd, SW_SHOW ); UpdateWindow( hwnd ); flush_events(); flush_sequence(); SetWindowLongPtrA( hwnd, GWLP_WNDPROC, (LONG_PTR)DispatchMessageCheckProc );
SetRect( &rect, -5, -5, 5, 5 ); RedrawWindow( hwnd, &rect, 0, RDW_INVALIDATE|RDW_ERASE|RDW_FRAME ); count = 0; while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) { if (msg.message != WM_PAINT) DispatchMessageA( &msg ); else { flush_sequence(); DispatchMessageA( &msg ); /* DispatchMessage will send WM_NCPAINT if non client area is still invalid after WM_PAINT */ if (!count) ok_sequence( WmDispatchPaint, "WmDispatchPaint", FALSE ); else ok_sequence( WmEmptySeq, "WmEmpty", FALSE ); if (++count > 10) break; } } ok( msg.message == WM_PAINT && count > 10, "WM_PAINT messages stopped\n" );
trace("now without DispatchMessage\n"); flush_sequence(); RedrawWindow( hwnd, &rect, 0, RDW_INVALIDATE|RDW_ERASE|RDW_FRAME ); count = 0; while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) { if (msg.message != WM_PAINT) DispatchMessageA( &msg ); else { HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 ); flush_sequence(); /* this will send WM_NCCPAINT just like DispatchMessage does */ GetUpdateRgn( hwnd, hrgn, TRUE ); ok_sequence( WmDispatchPaint, "WmDispatchPaint", FALSE ); DeleteObject( hrgn ); GetClientRect( hwnd, &rect ); ValidateRect( hwnd, &rect ); /* this will stop WM_PAINTs */ ok( !count, "Got multiple WM_PAINTs\n" ); if (++count > 10) break; } }
flush_sequence(); RedrawWindow( hwnd, &rect, 0, RDW_INVALIDATE|RDW_ERASE|RDW_FRAME ); count = 0; while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) { if (msg.message != WM_PAINT) DispatchMessageA( &msg ); else { HDC hdc;
flush_sequence(); hdc = BeginPaint( hwnd, NULL ); ok( !hdc, "got valid hdc %p from BeginPaint\n", hdc ); ok( !EndPaint( hwnd, NULL ), "EndPaint succeeded\n" ); ok_sequence( WmDispatchPaint, "WmDispatchPaint", FALSE ); ok( !count, "Got multiple WM_PAINTs\n" ); if (++count > 10) break; } } DestroyWindow(hwnd);}
static const struct message WmUser[] = { { WM_USER, sent }, { 0 }};
struct sendmsg_info{ HWND hwnd; DWORD timeout; DWORD ret;};
static DWORD CALLBACK send_msg_thread( LPVOID arg ){ struct sendmsg_info *info = arg; SetLastError( 0xdeadbeef ); info->ret = SendMessageTimeoutA( info->hwnd, WM_USER, 0, 0, 0, info->timeout, NULL ); if (!info->ret) ok( GetLastError() == ERROR_TIMEOUT || broken(GetLastError() == 0), /* win9x */ "unexpected error %d\n", GetLastError()); return 0;}
static void wait_for_thread( HANDLE thread ){ while (MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_SENDMESSAGE) != WAIT_OBJECT_0) { MSG msg; while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA(&msg); }}
static LRESULT WINAPI send_msg_delay_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ if (message == WM_USER) Sleep(200); return MsgCheckProcA( hwnd, message, wParam, lParam );}
static void test_SendMessageTimeout(void){ HANDLE thread; struct sendmsg_info info; DWORD tid; BOOL is_win9x;
info.hwnd = CreateWindowA( "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW, 100, 100, 200, 200, 0, 0, 0, NULL); flush_events(); flush_sequence();
info.timeout = 1000; info.ret = 0xdeadbeef; thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid ); wait_for_thread( thread ); CloseHandle( thread ); ok( info.ret == 1, "SendMessageTimeout failed\n" ); ok_sequence( WmUser, "WmUser", FALSE );
info.timeout = 1; info.ret = 0xdeadbeef; thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid ); Sleep(100); /* SendMessageTimeout should time out here */ wait_for_thread( thread ); CloseHandle( thread ); ok( info.ret == 0, "SendMessageTimeout succeeded\n" ); ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE );
/* 0 means infinite timeout (but not on win9x) */ info.timeout = 0; info.ret = 0xdeadbeef; thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid ); Sleep(100); wait_for_thread( thread ); CloseHandle( thread ); is_win9x = !info.ret; if (is_win9x) ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE ); else ok_sequence( WmUser, "WmUser", FALSE );
/* timeout is treated as signed despite the prototype (but not on win9x) */ info.timeout = 0x7fffffff; info.ret = 0xdeadbeef; thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid ); Sleep(100); wait_for_thread( thread ); CloseHandle( thread ); ok( info.ret == 1, "SendMessageTimeout failed\n" ); ok_sequence( WmUser, "WmUser", FALSE );
info.timeout = 0x80000000; info.ret = 0xdeadbeef; thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid ); Sleep(100); wait_for_thread( thread ); CloseHandle( thread ); if (is_win9x) { ok( info.ret == 1, "SendMessageTimeout failed\n" ); ok_sequence( WmUser, "WmUser", FALSE ); } else { ok( info.ret == 0, "SendMessageTimeout succeeded\n" ); ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE ); }
/* now check for timeout during message processing */ SetWindowLongPtrA( info.hwnd, GWLP_WNDPROC, (LONG_PTR)send_msg_delay_proc ); info.timeout = 100; info.ret = 0xdeadbeef; thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid ); wait_for_thread( thread ); CloseHandle( thread ); /* we should time out but still get the message */ ok( info.ret == 0, "SendMessageTimeout failed\n" ); ok_sequence( WmUser, "WmUser", FALSE );
DestroyWindow( info.hwnd );}
/****************** edit message test *************************/#define ID_EDIT 0x1234static const struct message sl_edit_setfocus[] ={ { HCBT_SETFOCUS, hook }, { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|wparam, 0 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 10 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 15 }, { WM_CTLCOLOREDIT, sent|parent }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 11 }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_SETFOCUS) }, { 0 }};static const struct message sl_edit_invisible[] ={ { HCBT_SETFOCUS, hook }, { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_KILLFOCUS, sent|parent }, { WM_SETFOCUS, sent }, { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_SETFOCUS) }, { 0 }};static const struct message ml_edit_setfocus[] ={ { HCBT_SETFOCUS, hook }, { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|wparam, 0 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 10 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 11 }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_SETFOCUS) }, { 0 }};static const struct message sl_edit_killfocus[] ={ { HCBT_SETFOCUS, hook }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_KILLFOCUS, sent|wparam, 0 }, { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_KILLFOCUS) }, { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 1 }, { 0 }};static const struct message sl_edit_lbutton_dblclk[] ={ { WM_LBUTTONDBLCLK, sent }, { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, { 0 }};static const struct message sl_edit_lbutton_down[] ={ { WM_LBUTTONDOWN, sent|wparam|lparam, 0, 0 }, { HCBT_SETFOCUS, hook }, { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 10 }, { WM_CTLCOLOREDIT, sent|parent }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 11 }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_SETFOCUS) }, { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, { WM_CTLCOLOREDIT, sent|parent|optional }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 11 }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, { 0 }};static const struct message ml_edit_lbutton_down[] ={ { WM_LBUTTONDOWN, sent|wparam|lparam, 0, 0 }, { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, { HCBT_SETFOCUS, hook }, { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 10 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 11 }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_SETFOCUS) }, { 0 }};static const struct message sl_edit_lbutton_up[] ={ { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 }, { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 }, { WM_CAPTURECHANGED, sent|defwinproc }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, { 0 }};static const struct message ml_edit_lbutton_up[] ={ { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 }, { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 }, { WM_CAPTURECHANGED, sent|defwinproc }, { 0 }};
static WNDPROC old_edit_proc;
static LRESULT CALLBACK edit_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ static LONG defwndproc_counter = 0; LRESULT ret; struct recvd_message msg;
if (ignore_message( message )) return 0;
msg.hwnd = hwnd; msg.message = message; msg.flags = sent|wparam|lparam; if (defwndproc_counter) msg.flags |= defwinproc; msg.wParam = wParam; msg.lParam = lParam; msg.descr = "edit"; add_message(&msg);
defwndproc_counter++; ret = CallWindowProcA(old_edit_proc, hwnd, message, wParam, lParam); defwndproc_counter--;
return ret;}
static void subclass_edit(void){ WNDCLASSA cls;
if (!GetClassInfoA(0, "edit", &cls)) assert(0);
old_edit_proc = cls.lpfnWndProc;
cls.hInstance = GetModuleHandleA(NULL); cls.lpfnWndProc = edit_hook_proc; cls.lpszClassName = "my_edit_class"; UnregisterClassA(cls.lpszClassName, cls.hInstance); if (!RegisterClassA(&cls)) assert(0);}
static void test_edit_messages(void){ HWND hwnd, parent; DWORD dlg_code;
subclass_edit(); log_all_parent_messages++;
parent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 200, 200, 0, 0, 0, NULL); ok (parent != 0, "Failed to create parent window\n");
/* test single line edit */ hwnd = CreateWindowExA(0, "my_edit_class", "test", WS_CHILD, 0, 0, 80, 20, parent, (HMENU)ID_EDIT, 0, NULL); ok(hwnd != 0, "Failed to create edit window\n");
dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0); ok(dlg_code == (DLGC_WANTCHARS|DLGC_HASSETSEL|DLGC_WANTARROWS), "wrong dlg_code %08x\n", dlg_code);
flush_sequence(); SetFocus(hwnd); ok_sequence(sl_edit_invisible, "SetFocus(hwnd) on an invisible edit", FALSE);
ShowWindow(hwnd, SW_SHOW); UpdateWindow(hwnd); SetFocus(0); flush_sequence();
SetFocus(hwnd); ok_sequence(sl_edit_setfocus, "SetFocus(hwnd) on an edit", FALSE);
SetFocus(0); ok_sequence(sl_edit_killfocus, "SetFocus(0) on an edit", FALSE);
SetFocus(0); ReleaseCapture(); flush_sequence();
SendMessageA(hwnd, WM_LBUTTONDBLCLK, 0, 0); ok_sequence(sl_edit_lbutton_dblclk, "WM_LBUTTONDBLCLK on an edit", FALSE);
SetFocus(0); ReleaseCapture(); flush_sequence();
SendMessageA(hwnd, WM_LBUTTONDOWN, 0, 0); ok_sequence(sl_edit_lbutton_down, "WM_LBUTTONDOWN on an edit", FALSE);
SendMessageA(hwnd, WM_LBUTTONUP, 0, 0); ok_sequence(sl_edit_lbutton_up, "WM_LBUTTONUP on an edit", FALSE);
DestroyWindow(hwnd);
/* test multiline edit */ hwnd = CreateWindowExA(0, "my_edit_class", "test", WS_CHILD | ES_MULTILINE, 0, 0, 80, 20, parent, (HMENU)ID_EDIT, 0, NULL); ok(hwnd != 0, "Failed to create edit window\n");
dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0); ok(dlg_code == (DLGC_WANTCHARS|DLGC_HASSETSEL|DLGC_WANTARROWS|DLGC_WANTALLKEYS), "wrong dlg_code %08x\n", dlg_code);
ShowWindow(hwnd, SW_SHOW); UpdateWindow(hwnd); SetFocus(0); flush_sequence();
SetFocus(hwnd); ok_sequence(ml_edit_setfocus, "SetFocus(hwnd) on multiline edit", FALSE);
SetFocus(0); ok_sequence(sl_edit_killfocus, "SetFocus(0) on multiline edit", FALSE);
SetFocus(0); ReleaseCapture(); flush_sequence();
SendMessageA(hwnd, WM_LBUTTONDBLCLK, 0, 0); ok_sequence(sl_edit_lbutton_dblclk, "WM_LBUTTONDBLCLK on multiline edit", FALSE);
SetFocus(0); ReleaseCapture(); flush_sequence();
SendMessageA(hwnd, WM_LBUTTONDOWN, 0, 0); ok_sequence(ml_edit_lbutton_down, "WM_LBUTTONDOWN on multiline edit", FALSE);
SendMessageA(hwnd, WM_LBUTTONUP, 0, 0); ok_sequence(ml_edit_lbutton_up, "WM_LBUTTONUP on multiline edit", FALSE);
DestroyWindow(hwnd); DestroyWindow(parent);
log_all_parent_messages--;}
/**************************** End of Edit test ******************************/
static const struct message WmKeyDownSkippedSeq[] ={ { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 1 }, /* XP */ { 0 }};static const struct message WmKeyDownWasDownSkippedSeq[] ={ { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0x40000001 }, /* XP */ { 0 }};static const struct message WmKeyUpSkippedSeq[] ={ { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */ { 0 }};static const struct message WmUserKeyUpSkippedSeq[] ={ { WM_USER, sent }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'N', 0xc0000001 }, /* XP */ { 0 }};
#define EV_STOP 0#define EV_SENDMSG 1#define EV_ACK 2
struct peekmsg_info{ HWND hwnd; HANDLE hevent[3]; /* 0 - start/stop, 1 - SendMessage, 2 - ack */};
static DWORD CALLBACK send_msg_thread_2(void *param){ DWORD ret; struct peekmsg_info *info = param;
trace("thread: looping\n"); SetEvent(info->hevent[EV_ACK]);
while (1) { ret = WaitForMultipleObjects(2, info->hevent, FALSE, INFINITE);
switch (ret) { case WAIT_OBJECT_0 + EV_STOP: trace("thread: exiting\n"); return 0;
case WAIT_OBJECT_0 + EV_SENDMSG: trace("thread: sending message\n"); ret = SendNotifyMessageA(info->hwnd, WM_USER, 0, 0); ok(ret, "SendNotifyMessageA failed error %u\n", GetLastError()); SetEvent(info->hevent[EV_ACK]); break;
default: trace("unexpected return: %04x\n", ret); assert(0); break; } } return 0;}
static void test_PeekMessage(void){ MSG msg; HANDLE hthread; DWORD tid, qstatus; UINT qs_all_input = QS_ALLINPUT; UINT qs_input = QS_INPUT; BOOL ret; struct peekmsg_info info;
info.hwnd = CreateWindowA("TestWindowClass", NULL, WS_OVERLAPPEDWINDOW, 100, 100, 200, 200, 0, 0, 0, NULL); assert(info.hwnd); ShowWindow(info.hwnd, SW_SHOW); UpdateWindow(info.hwnd); SetFocus(info.hwnd);
info.hevent[EV_STOP] = CreateEventA(NULL, 0, 0, NULL); info.hevent[EV_SENDMSG] = CreateEventA(NULL, 0, 0, NULL); info.hevent[EV_ACK] = CreateEventA(NULL, 0, 0, NULL);
hthread = CreateThread(NULL, 0, send_msg_thread_2, &info, 0, &tid); WaitForSingleObject(info.hevent[EV_ACK], 10000);
flush_events(); flush_sequence();
SetLastError(0xdeadbeef); qstatus = GetQueueStatus(qs_all_input); if (GetLastError() == ERROR_INVALID_FLAGS) { trace("QS_RAWINPUT not supported on this platform\n"); qs_all_input &= ~QS_RAWINPUT; qs_input &= ~QS_RAWINPUT; } if (qstatus & QS_POSTMESSAGE) { while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) /* nothing */ ; qstatus = GetQueueStatus(qs_all_input); } ok(qstatus == 0, "wrong qstatus %08x\n", qstatus);
trace("signalling to send message\n"); SetEvent(info.hevent[EV_SENDMSG]); WaitForSingleObject(info.hevent[EV_ACK], INFINITE);
/* pass invalid QS_xxxx flags */ SetLastError(0xdeadbeef); qstatus = GetQueueStatus(0xffffffff); ok(qstatus == 0 || broken(qstatus) /* win9x */, "GetQueueStatus should fail: %08x\n", qstatus); if (!qstatus) { ok(GetLastError() == ERROR_INVALID_FLAGS, "wrong error %d\n", GetLastError()); qstatus = GetQueueStatus(qs_all_input); } qstatus &= ~MAKELONG( 0x4000, 0x4000 ); /* sometimes set on Win95 */ ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE), "wrong qstatus %08x\n", qstatus);
msg.message = 0; ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE); ok(!ret, "PeekMessageA should have returned FALSE instead of msg %04x\n", msg.message); ok_sequence(WmUser, "WmUser", FALSE);
qstatus = GetQueueStatus(qs_all_input); ok(qstatus == 0, "wrong qstatus %08x\n", qstatus);
keybd_event('N', 0, 0, 0); keybd_event('N', 0, KEYEVENTF_KEYUP, 0); qstatus = GetQueueStatus(qs_all_input); if (!(qstatus & MAKELONG(QS_KEY, QS_KEY))) { skip( "queuing key events not supported\n" ); goto done; } ok(qstatus == MAKELONG(QS_KEY, QS_KEY) || /* keybd_event seems to trigger a sent message on NT4 */ qstatus == MAKELONG(QS_KEY|QS_SENDMESSAGE, QS_KEY|QS_SENDMESSAGE), "wrong qstatus %08x\n", qstatus);
PostMessageA(info.hwnd, WM_CHAR, 'z', 0); qstatus = GetQueueStatus(qs_all_input); ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE|QS_KEY) || qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE|QS_KEY|QS_SENDMESSAGE), "wrong qstatus %08x\n", qstatus);
InvalidateRect(info.hwnd, NULL, FALSE); qstatus = GetQueueStatus(qs_all_input); ok(qstatus == MAKELONG(QS_PAINT, QS_PAINT|QS_POSTMESSAGE|QS_KEY) || qstatus == MAKELONG(QS_PAINT, QS_PAINT|QS_POSTMESSAGE|QS_KEY|QS_SENDMESSAGE), "wrong qstatus %08x\n", qstatus);
trace("signalling to send message\n"); SetEvent(info.hevent[EV_SENDMSG]); WaitForSingleObject(info.hevent[EV_ACK], INFINITE);
qstatus = GetQueueStatus(qs_all_input); ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_PAINT|QS_POSTMESSAGE|QS_KEY), "wrong qstatus %08x\n", qstatus);
msg.message = 0; ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | (qs_input << 16)); if (ret && msg.message == WM_CHAR) { win_skip( "PM_QS_* flags not supported in PeekMessage\n" ); goto done; } ok(!ret, "PeekMessageA should have returned FALSE instead of msg %04x\n", msg.message); if (!sequence_cnt) /* nt4 doesn't fetch anything with PM_QS_* flags */ { win_skip( "PM_QS_* flags not supported in PeekMessage\n" ); goto done; } ok_sequence(WmUser, "WmUser", FALSE);
qstatus = GetQueueStatus(qs_all_input); ok(qstatus == MAKELONG(0, QS_PAINT|QS_POSTMESSAGE|QS_KEY), "wrong qstatus %08x\n", qstatus);
trace("signalling to send message\n"); SetEvent(info.hevent[EV_SENDMSG]); WaitForSingleObject(info.hevent[EV_ACK], INFINITE);
qstatus = GetQueueStatus(qs_all_input); ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_PAINT|QS_POSTMESSAGE|QS_KEY), "wrong qstatus %08x\n", qstatus);
msg.message = 0; ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_POSTMESSAGE ); ok(!ret, "PeekMessageA should have returned FALSE instead of msg %04x\n", msg.message); ok_sequence(WmUser, "WmUser", FALSE);
qstatus = GetQueueStatus(qs_all_input); ok(qstatus == MAKELONG(0, QS_PAINT|QS_POSTMESSAGE|QS_KEY), "wrong qstatus %08x\n", qstatus);
msg.message = 0; ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_POSTMESSAGE); ok(ret && msg.message == WM_CHAR && msg.wParam == 'z', "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n", ret, msg.message, msg.wParam); ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE);
qstatus = GetQueueStatus(qs_all_input); ok(qstatus == MAKELONG(0, QS_PAINT|QS_KEY), "wrong qstatus %08x\n", qstatus);
msg.message = 0; ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_POSTMESSAGE); ok(!ret, "PeekMessageA should have returned FALSE instead of msg %04x\n", msg.message); ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE);
qstatus = GetQueueStatus(qs_all_input); ok(qstatus == MAKELONG(0, QS_PAINT|QS_KEY), "wrong qstatus %08x\n", qstatus);
msg.message = 0; ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_PAINT); ok(ret && msg.message == WM_PAINT, "got %d and %04x instead of TRUE and WM_PAINT\n", ret, msg.message); DispatchMessageA(&msg); ok_sequence(WmPaint, "WmPaint", FALSE);
qstatus = GetQueueStatus(qs_all_input); ok(qstatus == MAKELONG(0, QS_KEY), "wrong qstatus %08x\n", qstatus);
msg.message = 0; ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_PAINT); ok(!ret, "PeekMessageA should have returned FALSE instead of msg %04x\n", msg.message); ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE);
qstatus = GetQueueStatus(qs_all_input); ok(qstatus == MAKELONG(0, QS_KEY), "wrong qstatus %08x\n", qstatus);
trace("signalling to send message\n"); SetEvent(info.hevent[EV_SENDMSG]); WaitForSingleObject(info.hevent[EV_ACK], INFINITE);
qstatus = GetQueueStatus(qs_all_input); ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_KEY), "wrong qstatus %08x\n", qstatus);
PostMessageA(info.hwnd, WM_CHAR, 'z', 0);
qstatus = GetQueueStatus(qs_all_input); ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_SENDMESSAGE|QS_POSTMESSAGE|QS_KEY), "wrong qstatus %08x\n", qstatus);
msg.message = 0; ret = PeekMessageA(&msg, 0, WM_CHAR, WM_CHAR, PM_REMOVE); ok(ret && msg.message == WM_CHAR && msg.wParam == 'z', "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n", ret, msg.message, msg.wParam); ok_sequence(WmUser, "WmUser", FALSE);
qstatus = GetQueueStatus(qs_all_input); ok(qstatus == MAKELONG(0, QS_KEY), "wrong qstatus %08x\n", qstatus);
msg.message = 0; ret = PeekMessageA(&msg, 0, WM_CHAR, WM_CHAR, PM_REMOVE); ok(!ret, "PeekMessageA should have returned FALSE instead of msg %04x\n", msg.message); ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE);
qstatus = GetQueueStatus(qs_all_input); ok(qstatus == MAKELONG(0, QS_KEY), "wrong qstatus %08x\n", qstatus);
PostMessageA(info.hwnd, WM_CHAR, 'z', 0);
qstatus = GetQueueStatus(qs_all_input); ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE|QS_KEY), "wrong qstatus %08x\n", qstatus);
trace("signalling to send message\n"); SetEvent(info.hevent[EV_SENDMSG]); WaitForSingleObject(info.hevent[EV_ACK], INFINITE);
qstatus = GetQueueStatus(qs_all_input); ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_POSTMESSAGE|QS_KEY), "wrong qstatus %08x\n", qstatus);
msg.message = 0; ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | (QS_KEY << 16)); ok(!ret, "PeekMessageA should have returned FALSE instead of msg %04x\n", msg.message); ok_sequence(WmUser, "WmUser", FALSE);
qstatus = GetQueueStatus(qs_all_input); ok(qstatus == MAKELONG(0, QS_POSTMESSAGE|QS_KEY), "wrong qstatus %08x\n", qstatus);
msg.message = 0; if (qs_all_input & QS_RAWINPUT) /* use QS_RAWINPUT only if supported */ ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | (QS_RAWINPUT << 16)); else /* workaround for a missing QS_RAWINPUT support */ ret = PeekMessageA(&msg, 0, WM_KEYDOWN, WM_KEYDOWN, PM_REMOVE); ok(ret && msg.message == WM_KEYDOWN && msg.wParam == 'N', "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n", ret, msg.message, msg.wParam); ok_sequence(WmKeyDownSkippedSeq, "WmKeyDownSkippedSeq", FALSE);
qstatus = GetQueueStatus(qs_all_input); ok(qstatus == MAKELONG(0, QS_POSTMESSAGE|QS_KEY), "wrong qstatus %08x\n", qstatus);
msg.message = 0; if (qs_all_input & QS_RAWINPUT) /* use QS_RAWINPUT only if supported */ ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | (QS_RAWINPUT << 16)); else /* workaround for a missing QS_RAWINPUT support */ ret = PeekMessageA(&msg, 0, WM_KEYUP, WM_KEYUP, PM_REMOVE); ok(ret && msg.message == WM_KEYUP && msg.wParam == 'N', "got %d and %04x wParam %08lx instead of TRUE and WM_KEYUP wParam 'N'\n", ret, msg.message, msg.wParam); ok_sequence(WmKeyUpSkippedSeq, "WmKeyUpSkippedSeq", FALSE);
qstatus = GetQueueStatus(qs_all_input); ok(qstatus == MAKELONG(0, QS_POSTMESSAGE), "wrong qstatus %08x\n", qstatus);
msg.message = 0; ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE); ok(!ret, "PeekMessageA should have returned FALSE instead of msg %04x\n", msg.message); ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE);
qstatus = GetQueueStatus(qs_all_input); ok(qstatus == MAKELONG(0, QS_POSTMESSAGE), "wrong qstatus %08x\n", qstatus);
msg.message = 0; ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE); ok(ret && msg.message == WM_CHAR && msg.wParam == 'z', "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n", ret, msg.message, msg.wParam); ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE);
qstatus = GetQueueStatus(qs_all_input); ok(qstatus == 0, "wrong qstatus %08x\n", qstatus);
msg.message = 0; ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE); ok(!ret, "PeekMessageA should have returned FALSE instead of msg %04x\n", msg.message); ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE);
qstatus = GetQueueStatus(qs_all_input); ok(qstatus == 0, "wrong qstatus %08x\n", qstatus);
/* test whether presence of the quit flag in the queue affects * the queue state */ PostQuitMessage(0x1234abcd);
qstatus = GetQueueStatus(qs_all_input); ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE), "wrong qstatus %08x\n", qstatus);
PostMessageA(info.hwnd, WM_USER, 0, 0);
qstatus = GetQueueStatus(qs_all_input); ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE), "wrong qstatus %08x\n", qstatus);
msg.message = 0; ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE); ok(ret && msg.message == WM_USER, "got %d and %04x instead of TRUE and WM_USER\n", ret, msg.message); ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE);
qstatus = GetQueueStatus(qs_all_input); ok(qstatus == MAKELONG(0, QS_POSTMESSAGE), "wrong qstatus %08x\n", qstatus);
msg.message = 0; ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE); ok(ret && msg.message == WM_QUIT, "got %d and %04x instead of TRUE and WM_QUIT\n", ret, msg.message); ok(msg.wParam == 0x1234abcd, "got wParam %08lx instead of 0x1234abcd\n", msg.wParam); ok(msg.lParam == 0, "got lParam %08lx instead of 0\n", msg.lParam); ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE);
qstatus = GetQueueStatus(qs_all_input);todo_wine { ok(qstatus == MAKELONG(0, QS_POSTMESSAGE), "wrong qstatus %08x\n", qstatus);}
msg.message = 0; ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE); ok(!ret, "PeekMessageA should have returned FALSE instead of msg %04x\n", msg.message); ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE);
qstatus = GetQueueStatus(qs_all_input); ok(qstatus == 0, "wrong qstatus %08x\n", qstatus);
/* some GetMessage tests */
keybd_event('N', 0, 0, 0); qstatus = GetQueueStatus(qs_all_input); ok(qstatus == MAKELONG(QS_KEY, QS_KEY), "wrong qstatus %08x\n", qstatus);
PostMessageA(info.hwnd, WM_CHAR, 'z', 0); qstatus = GetQueueStatus(qs_all_input); ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE|QS_KEY), "wrong qstatus %08x\n", qstatus);
if (qstatus) { ret = GetMessageA( &msg, 0, 0, 0 ); ok(ret && msg.message == WM_CHAR && msg.wParam == 'z', "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n", ret, msg.message, msg.wParam); qstatus = GetQueueStatus(qs_all_input); ok(qstatus == MAKELONG(0, QS_KEY), "wrong qstatus %08x\n", qstatus); }
if (qstatus) { ret = GetMessageA( &msg, 0, 0, 0 ); ok(ret && msg.message == WM_KEYDOWN && msg.wParam == 'N', "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n", ret, msg.message, msg.wParam); ok_sequence(WmKeyDownSkippedSeq, "WmKeyDownSkippedSeq", FALSE); qstatus = GetQueueStatus(qs_all_input); ok(qstatus == 0, "wrong qstatus %08x\n", qstatus); }
keybd_event('N', 0, 0, 0); qstatus = GetQueueStatus(qs_all_input); ok(qstatus == MAKELONG(QS_KEY, QS_KEY), "wrong qstatus %08x\n", qstatus);
PostMessageA(info.hwnd, WM_CHAR, 'z', 0); qstatus = GetQueueStatus(qs_all_input); ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE|QS_KEY), "wrong qstatus %08x\n", qstatus);
if (qstatus & (QS_KEY << 16)) { ret = GetMessageA( &msg, 0, WM_KEYDOWN, WM_KEYUP ); ok(ret && msg.message == WM_KEYDOWN && msg.wParam == 'N', "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n", ret, msg.message, msg.wParam); ok_sequence(WmKeyDownWasDownSkippedSeq, "WmKeyDownWasDownSkippedSeq", FALSE); qstatus = GetQueueStatus(qs_all_input); ok(qstatus == MAKELONG(0, QS_POSTMESSAGE), "wrong qstatus %08x\n", qstatus); }
if (qstatus) { ret = GetMessageA( &msg, 0, WM_CHAR, WM_CHAR ); ok(ret && msg.message == WM_CHAR && msg.wParam == 'z', "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n", ret, msg.message, msg.wParam); qstatus = GetQueueStatus(qs_all_input); ok(qstatus == 0, "wrong qstatus %08x\n", qstatus); }
keybd_event('N', 0, KEYEVENTF_KEYUP, 0); qstatus = GetQueueStatus(qs_all_input); ok(qstatus == MAKELONG(QS_KEY, QS_KEY), "wrong qstatus %08x\n", qstatus);
PostMessageA(info.hwnd, WM_CHAR, 'z', 0); qstatus = GetQueueStatus(qs_all_input); ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE|QS_KEY), "wrong qstatus %08x\n", qstatus);
trace("signalling to send message\n"); SetEvent(info.hevent[EV_SENDMSG]); WaitForSingleObject(info.hevent[EV_ACK], INFINITE); qstatus = GetQueueStatus(qs_all_input); ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_POSTMESSAGE|QS_KEY), "wrong qstatus %08x\n", qstatus);
if (qstatus & (QS_KEY << 16)) { ret = GetMessageA( &msg, 0, WM_KEYDOWN, WM_KEYUP ); ok(ret && msg.message == WM_KEYUP && msg.wParam == 'N', "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n", ret, msg.message, msg.wParam); ok_sequence(WmUserKeyUpSkippedSeq, "WmUserKeyUpSkippedSeq", FALSE); qstatus = GetQueueStatus(qs_all_input); ok(qstatus == MAKELONG(0, QS_POSTMESSAGE), "wrong qstatus %08x\n", qstatus); }
if (qstatus) { ret = GetMessageA( &msg, 0, WM_CHAR, WM_CHAR ); ok(ret && msg.message == WM_CHAR && msg.wParam == 'z', "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n", ret, msg.message, msg.wParam); qstatus = GetQueueStatus(qs_all_input); ok(qstatus == 0, "wrong qstatus %08x\n", qstatus); }
PostThreadMessageA(GetCurrentThreadId(), WM_USER, 0, 0); ret = PeekMessageA(&msg, (HWND)-1, 0, 0, PM_NOREMOVE); ok(ret == TRUE, "wrong ret %d\n", ret); ok(msg.message == WM_USER, "wrong message %u\n", msg.message); ret = GetMessageA(&msg, (HWND)-1, 0, 0); ok(ret == TRUE, "wrong ret %d\n", ret); ok(msg.message == WM_USER, "wrong message %u\n", msg.message);
PostThreadMessageA(GetCurrentThreadId(), WM_USER, 0, 0); ret = PeekMessageA(&msg, (HWND)1, 0, 0, PM_NOREMOVE); ok(ret == TRUE, "wrong ret %d\n", ret); ok(msg.message == WM_USER, "wrong message %u\n", msg.message); ret = GetMessageA(&msg, (HWND)1, 0, 0); ok(ret == TRUE, "wrong ret %d\n", ret); ok(msg.message == WM_USER, "wrong message %u\n", msg.message);
PostThreadMessageA(GetCurrentThreadId(), WM_USER, 0, 0); ret = PeekMessageA(&msg, (HWND)0xffff, 0, 0, PM_NOREMOVE); ok(ret == TRUE, "wrong ret %d\n", ret); ok(msg.message == WM_USER, "wrong message %u\n", msg.message); ret = GetMessageA(&msg, (HWND)0xffff, 0, 0); ok(ret == TRUE, "wrong ret %d\n", ret); ok(msg.message == WM_USER, "wrong message %u\n", msg.message);
done: trace("signalling to exit\n"); SetEvent(info.hevent[EV_STOP]);
WaitForSingleObject(hthread, INFINITE);
CloseHandle(hthread); CloseHandle(info.hevent[0]); CloseHandle(info.hevent[1]); CloseHandle(info.hevent[2]);
DestroyWindow(info.hwnd);}
static void wait_move_event(HWND hwnd, int x, int y){ MSG msg; DWORD time; BOOL ret;
time = GetTickCount(); while (GetTickCount() - time < 200) { ret = PeekMessageA(&msg, hwnd, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_NOREMOVE); if (ret && msg.pt.x > x && msg.pt.y > y) break; if (!ret) MsgWaitForMultipleObjects( 0, NULL, FALSE, GetTickCount() - time, QS_ALLINPUT ); else Sleep( GetTickCount() - time ); }}
#define STEP 5static void test_PeekMessage2(void){ HWND hwnd; BOOL ret; MSG msg; UINT message; DWORD time1, time2, time3; int x1, y1, x2, y2, x3, y3; POINT pos;
time1 = time2 = time3 = 0; x1 = y1 = x2 = y2 = x3 = y3 = 0;
/* Initialise window and make sure it is ready for events */ hwnd = CreateWindowA("TestWindowClass", "PeekMessage2", WS_OVERLAPPEDWINDOW, 10, 10, 800, 800, NULL, NULL, NULL, NULL); assert(hwnd); trace("Window for test_PeekMessage2 %p\n", hwnd); ShowWindow(hwnd, SW_SHOW); UpdateWindow(hwnd); SetFocus(hwnd); GetCursorPos(&pos); SetCursorPos(100, 100); mouse_event(MOUSEEVENTF_MOVE, -STEP, -STEP, 0, 0); flush_events();
/* Do initial mousemove, wait until we can see it and then do our test peek with PM_NOREMOVE. */ mouse_event(MOUSEEVENTF_MOVE, STEP, STEP, 0, 0); wait_move_event(hwnd, 100-STEP, 100-STEP);
ret = PeekMessageA(&msg, hwnd, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_NOREMOVE); if (!ret) { skip( "queuing mouse events not supported\n" ); goto done; } else { trace("1st move event: %04x %x %d %d\n", msg.message, msg.time, msg.pt.x, msg.pt.y); message = msg.message; time1 = msg.time; x1 = msg.pt.x; y1 = msg.pt.y; ok(message == WM_MOUSEMOVE, "message not WM_MOUSEMOVE, %04x instead\n", message); }
/* Allow time to advance a bit, and then simulate the user moving their * mouse around. After that we peek again with PM_NOREMOVE. * Although the previous mousemove message was never removed, the * mousemove we now peek should reflect the recent mouse movements * because the input queue will merge the move events. */ Sleep(100); mouse_event(MOUSEEVENTF_MOVE, STEP, STEP, 0, 0); wait_move_event(hwnd, x1, y1);
ret = PeekMessageA(&msg, hwnd, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_NOREMOVE); ok(ret, "no message available\n"); if (ret) { trace("2nd move event: %04x %x %d %d\n", msg.message, msg.time, msg.pt.x, msg.pt.y); message = msg.message; time2 = msg.time; x2 = msg.pt.x; y2 = msg.pt.y; ok(message == WM_MOUSEMOVE, "message not WM_MOUSEMOVE, %04x instead\n", message); ok(time2 > time1, "message time not advanced: %x %x\n", time1, time2); ok(x2 != x1 && y2 != y1, "coords not changed: (%d %d) (%d %d)\n", x1, y1, x2, y2); }
/* Have another go, to drive the point home */ Sleep(100); mouse_event(MOUSEEVENTF_MOVE, STEP, STEP, 0, 0); wait_move_event(hwnd, x2, y2);
ret = PeekMessageA(&msg, hwnd, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_NOREMOVE); ok(ret, "no message available\n"); if (ret) { trace("3rd move event: %04x %x %d %d\n", msg.message, msg.time, msg.pt.x, msg.pt.y); message = msg.message; time3 = msg.time; x3 = msg.pt.x; y3 = msg.pt.y; ok(message == WM_MOUSEMOVE, "message not WM_MOUSEMOVE, %04x instead\n", message); ok(time3 > time2, "message time not advanced: %x %x\n", time2, time3); ok(x3 != x2 && y3 != y2, "coords not changed: (%d %d) (%d %d)\n", x2, y2, x3, y3); }
done: DestroyWindow(hwnd); SetCursorPos(pos.x, pos.y); flush_events();}
static void test_PeekMessage3(void){ HWND hwnd; BOOL ret; MSG msg;
hwnd = CreateWindowA("TestWindowClass", "PeekMessage3", WS_OVERLAPPEDWINDOW, 10, 10, 800, 800, NULL, NULL, NULL, NULL); ok(hwnd != NULL, "expected hwnd != NULL\n"); flush_events();
/* GetMessage() and PeekMessage(..., PM_REMOVE) should prefer messages which * were already seen. */
SetTimer(hwnd, 1, 0, NULL); while (!PeekMessageA(&msg, NULL, 0, 0, PM_NOREMOVE)); ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); PostMessageA(hwnd, WM_USER, 0, 0); ret = PeekMessageA(&msg, NULL, 0, 0, PM_NOREMOVE); ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); ret = GetMessageA(&msg, NULL, 0, 0); ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); ret = GetMessageA(&msg, NULL, 0, 0); ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); ret = PeekMessageA(&msg, NULL, 0, 0, 0); ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret);
SetTimer(hwnd, 1, 0, NULL); while (!PeekMessageA(&msg, NULL, 0, 0, PM_NOREMOVE)); ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); PostMessageA(hwnd, WM_USER, 0, 0); ret = PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE); ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); ret = PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE); ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); ret = PeekMessageA(&msg, NULL, 0, 0, 0); ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret);
/* It doesn't matter if a message range is specified or not. */
SetTimer(hwnd, 1, 0, NULL); while (!PeekMessageA(&msg, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE)); ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); PostMessageA(hwnd, WM_USER, 0, 0); ret = GetMessageA(&msg, NULL, 0, 0); ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); ret = GetMessageA(&msg, NULL, 0, 0); ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); ret = PeekMessageA(&msg, NULL, 0, 0, 0); ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret);
/* But not if the post messages were added before the PeekMessage() call. */
PostMessageA(hwnd, WM_USER, 0, 0); SetTimer(hwnd, 1, 0, NULL); while (!PeekMessageA(&msg, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE)); ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); ret = GetMessageA(&msg, NULL, 0, 0); ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); ret = GetMessageA(&msg, NULL, 0, 0); ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); ret = PeekMessageA(&msg, NULL, 0, 0, 0); ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret);
/* More complicated test with multiple messages. */
PostMessageA(hwnd, WM_USER, 0, 0); SetTimer(hwnd, 1, 0, NULL); while (!PeekMessageA(&msg, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE)); ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); PostMessageA(hwnd, WM_USER + 1, 0, 0); ret = GetMessageA(&msg, NULL, 0, 0); ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); ret = GetMessageA(&msg, NULL, 0, 0); ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); ret = GetMessageA(&msg, NULL, 0, 0); ok(ret && msg.message == WM_USER + 1, "msg.message = %u instead of WM_USER + 1\n", msg.message); ret = PeekMessageA(&msg, NULL, 0, 0, 0); ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret);
/* Newer messages are still returned when specifying a message range. */
SetTimer(hwnd, 1, 0, NULL); while (!PeekMessageA(&msg, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE)); ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); PostMessageA(hwnd, WM_USER + 1, 0, 0); PostMessageA(hwnd, WM_USER, 0, 0); ret = PeekMessageA(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); ret = PeekMessageA(&msg, NULL, WM_USER, WM_USER + 1, PM_NOREMOVE); ok(ret && msg.message == WM_USER + 1, "msg.message = %u instead of WM_USER + 1\n", msg.message); ret = PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE); ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); ret = PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE); ok(ret && msg.message == WM_USER + 1, "msg.message = %u instead of WM_USER + 1\n", msg.message); ret = PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE); ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); ret = PeekMessageA(&msg, NULL, 0, 0, 0); ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret);
/* Also works for posted messages, but the situation is a bit different, * because both messages are in the same queue. */
PostMessageA(hwnd, WM_TIMER, 0, 0); while (!PeekMessageA(&msg, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE)); ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); PostMessageA(hwnd, WM_USER, 0, 0); ret = GetMessageA(&msg, NULL, 0, 0); ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); ret = GetMessageA(&msg, NULL, 0, 0); ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); ret = PeekMessageA(&msg, NULL, 0, 0, 0); ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret);
PostMessageA(hwnd, WM_USER, 0, 0); PostMessageA(hwnd, WM_TIMER, 0, 0); while (!PeekMessageA(&msg, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE)); ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); ret = GetMessageA(&msg, NULL, 0, 0); ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message); ret = GetMessageA(&msg, NULL, 0, 0); ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message); ret = PeekMessageA(&msg, NULL, 0, 0, 0); ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret);
DestroyWindow(hwnd); flush_events();}
static INT_PTR CALLBACK wm_quit_dlg_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp){ struct recvd_message msg;
if (ignore_message( message )) return 0;
msg.hwnd = hwnd; msg.message = message; msg.flags = sent|wparam|lparam; msg.wParam = wp; msg.lParam = lp; msg.descr = "dialog"; add_message(&msg);
switch (message) { case WM_INITDIALOG: PostMessageA(hwnd, WM_QUIT, 0x1234, 0x5678); PostMessageA(hwnd, WM_USER, 0xdead, 0xbeef); return 0;
case WM_GETDLGCODE: return 0;
case WM_USER: EndDialog(hwnd, 0); break; }
return 1;}
static const struct message WmQuitDialogSeq[] = { { HCBT_CREATEWND, hook }, { WM_SETFONT, sent }, { WM_INITDIALOG, sent }, { WM_CHANGEUISTATE, sent|optional }, { HCBT_DESTROYWND, hook }, { 0x0090, sent|optional }, /* Vista */ { WM_DESTROY, sent }, { WM_NCDESTROY, sent }, { 0 }};
static const struct message WmStopQuitSeq[] = { { WM_DWMNCRENDERINGCHANGED, posted|optional }, { WM_CLOSE, posted }, { WM_QUIT, posted|wparam|lparam, 0x1234, 0 }, { 0 }};
static void test_quit_message(void){ MSG msg; BOOL ret;
/* test using PostQuitMessage */ flush_events(); PostQuitMessage(0xbeef);
msg.message = 0; ret = PeekMessageA(&msg, 0, 0, 0, PM_QS_SENDMESSAGE); ok(!ret, "got %x message\n", msg.message);
ret = PeekMessageA(&msg, NULL, 0, 0, PM_NOREMOVE); ok(ret, "PeekMessage failed with error %d\n", GetLastError()); ok(msg.message == WM_QUIT, "Received message 0x%04x instead of WM_QUIT\n", msg.message); ok(msg.wParam == 0xbeef, "wParam was 0x%lx instead of 0xbeef\n", msg.wParam);
ret = PostThreadMessageA(GetCurrentThreadId(), WM_USER, 0, 0); ok(ret, "PostMessage failed with error %d\n", GetLastError());
ret = GetMessageA(&msg, NULL, 0, 0); ok(ret > 0, "GetMessage failed with error %d\n", GetLastError()); ok(msg.message == WM_USER, "Received message 0x%04x instead of WM_USER\n", msg.message);
/* note: WM_QUIT message received after WM_USER message */ ret = GetMessageA(&msg, NULL, 0, 0); ok(!ret, "GetMessage return %d with error %d instead of FALSE\n", ret, GetLastError()); ok(msg.message == WM_QUIT, "Received message 0x%04x instead of WM_QUIT\n", msg.message); ok(msg.wParam == 0xbeef, "wParam was 0x%lx instead of 0xbeef\n", msg.wParam);
ret = PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE); ok( !ret || msg.message != WM_QUIT, "Received WM_QUIT again\n" );
/* now test with PostThreadMessage - different behaviour! */ PostThreadMessageA(GetCurrentThreadId(), WM_QUIT, 0xdead, 0);
ret = PeekMessageA(&msg, NULL, 0, 0, PM_NOREMOVE); ok(ret, "PeekMessage failed with error %d\n", GetLastError()); ok(msg.message == WM_QUIT, "Received message 0x%04x instead of WM_QUIT\n", msg.message); ok(msg.wParam == 0xdead, "wParam was 0x%lx instead of 0xdead\n", msg.wParam);
ret = PostThreadMessageA(GetCurrentThreadId(), WM_USER, 0, 0); ok(ret, "PostMessage failed with error %d\n", GetLastError());
/* note: we receive the WM_QUIT message first this time */ ret = GetMessageA(&msg, NULL, 0, 0); ok(!ret, "GetMessage return %d with error %d instead of FALSE\n", ret, GetLastError()); ok(msg.message == WM_QUIT, "Received message 0x%04x instead of WM_QUIT\n", msg.message); ok(msg.wParam == 0xdead, "wParam was 0x%lx instead of 0xdead\n", msg.wParam);
ret = GetMessageA(&msg, NULL, 0, 0); ok(ret > 0, "GetMessage failed with error %d\n", GetLastError()); ok(msg.message == WM_USER, "Received message 0x%04x instead of WM_USER\n", msg.message);
flush_events(); flush_sequence(); ret = DialogBoxParamA(GetModuleHandleA(NULL), "TEST_EMPTY_DIALOG", 0, wm_quit_dlg_proc, 0); ok(ret == 1, "expected 1, got %d\n", ret); ok_sequence(WmQuitDialogSeq, "WmQuitDialogSeq", FALSE); memset(&msg, 0xab, sizeof(msg)); ret = PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE); ok(ret, "PeekMessage failed\n"); ok(msg.message == WM_QUIT, "Received message 0x%04x instead of WM_QUIT\n", msg.message); ok(msg.wParam == 0x1234, "wParam was 0x%lx instead of 0x1234\n", msg.wParam); ok(msg.lParam == 0, "lParam was 0x%lx instead of 0\n", msg.lParam);
/* Check what happens to a WM_QUIT message posted to a window that gets * destroyed. */ CreateWindowExA(0, "StopQuitClass", "Stop Quit Test", WS_OVERLAPPEDWINDOW, 0, 0, 100, 100, NULL, NULL, NULL, NULL); flush_sequence(); while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) { struct recvd_message rmsg; rmsg.hwnd = msg.hwnd; rmsg.message = msg.message; rmsg.flags = posted|wparam|lparam; rmsg.wParam = msg.wParam; rmsg.lParam = msg.lParam; rmsg.descr = "stop/quit"; if (msg.message == WM_QUIT) /* The hwnd can only be checked here */ ok(!msg.hwnd, "The WM_QUIT hwnd was %p instead of NULL\n", msg.hwnd); add_message(&rmsg); DispatchMessageA(&msg); } ok_sequence(WmStopQuitSeq, "WmStopQuitSeq", FALSE);}
static const struct message WmNotifySeq[] = { { WM_NOTIFY, sent|wparam|lparam, 0x1234, 0xdeadbeef }, { 0 }};
static void test_notify_message(void){ HWND hwnd; BOOL ret; MSG msg;
hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0, NULL, NULL, 0); ok(hwnd != 0, "Failed to create window\n"); flush_events(); flush_sequence();
ret = SendNotifyMessageA(hwnd, WM_NOTIFY, 0x1234, 0xdeadbeef); ok(ret == TRUE, "SendNotifyMessageA failed with error %u\n", GetLastError()); ok_sequence(WmNotifySeq, "WmNotifySeq", FALSE);
ret = SendNotifyMessageW(hwnd, WM_NOTIFY, 0x1234, 0xdeadbeef); ok(ret == TRUE, "SendNotifyMessageW failed with error %u\n", GetLastError()); ok_sequence(WmNotifySeq, "WmNotifySeq", FALSE);
ret = SendMessageCallbackA(hwnd, WM_NOTIFY, 0x1234, 0xdeadbeef, NULL, 0); ok(ret == TRUE, "SendMessageCallbackA failed with error %u\n", GetLastError()); ok_sequence(WmNotifySeq, "WmNotifySeq", FALSE);
ret = SendMessageCallbackW(hwnd, WM_NOTIFY, 0x1234, 0xdeadbeef, NULL, 0); ok(ret == TRUE, "SendMessageCallbackW failed with error %u\n", GetLastError()); ok_sequence(WmNotifySeq, "WmNotifySeq", FALSE);
ret = PostMessageA(hwnd, WM_NOTIFY, 0x1234, 0xdeadbeef); ok(ret == TRUE, "PostMessageA failed with error %u\n", GetLastError()); flush_events(); ok_sequence(WmNotifySeq, "WmNotifySeq", FALSE);
ret = PostMessageW(hwnd, WM_NOTIFY, 0x1234, 0xdeadbeef); ok(ret == TRUE, "PostMessageW failed with error %u\n", GetLastError()); flush_events(); ok_sequence(WmNotifySeq, "WmNotifySeq", FALSE);
ret = PostThreadMessageA(GetCurrentThreadId(), WM_NOTIFY, 0x1234, 0xdeadbeef); ok(ret == TRUE, "PostThreadMessageA failed with error %u\n", GetLastError()); while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) { msg.hwnd = hwnd; DispatchMessageA(&msg); } ok_sequence(WmNotifySeq, "WmNotifySeq", FALSE);
ret = PostThreadMessageW(GetCurrentThreadId(), WM_NOTIFY, 0x1234, 0xdeadbeef); ok(ret == TRUE, "PostThreadMessageW failed with error %u\n", GetLastError()); while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) { msg.hwnd = hwnd; DispatchMessageA(&msg); } ok_sequence(WmNotifySeq, "WmNotifySeq", FALSE);
DestroyWindow(hwnd);}
static const struct message WmMouseHoverSeq[] = { { WM_MOUSEACTIVATE, sent|optional }, /* we can get those when moving the mouse in focus-follow-mouse mode under X11 */ { WM_MOUSEACTIVATE, sent|optional }, { WM_TIMER, sent|optional }, /* XP sends it */ { WM_SYSTIMER, sent }, { WM_MOUSEHOVER, sent|wparam, 0 }, { 0 }};
static void pump_msg_loop_timeout(DWORD timeout, BOOL inject_mouse_move){ MSG msg; DWORD start_ticks, end_ticks;
start_ticks = GetTickCount(); /* add some deviation (50%) to cover not expected delays */ start_ticks += timeout / 2;
do { while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) { /* Timer proc messages are not dispatched to the window proc, * and therefore not logged. */ if ((msg.message == WM_TIMER || msg.message == WM_SYSTIMER) && msg.hwnd) { struct recvd_message s_msg;
s_msg.hwnd = msg.hwnd; s_msg.message = msg.message; s_msg.flags = sent|wparam|lparam; s_msg.wParam = msg.wParam; s_msg.lParam = msg.lParam; s_msg.descr = "msg_loop"; add_message(&s_msg); } DispatchMessageA(&msg); }
end_ticks = GetTickCount();
/* inject WM_MOUSEMOVE to see how it changes tracking */ if (inject_mouse_move && start_ticks + timeout / 2 >= end_ticks) { mouse_event(MOUSEEVENTF_MOVE, -1, 0, 0, 0); mouse_event(MOUSEEVENTF_MOVE, 1, 0, 0, 0);
inject_mouse_move = FALSE; } } while (start_ticks + timeout >= end_ticks);}
static void test_TrackMouseEvent(void){ TRACKMOUSEEVENT tme; BOOL ret; HWND hwnd, hchild; RECT rc_parent, rc_child; UINT default_hover_time, hover_width = 0, hover_height = 0;
#define track_hover(track_hwnd, track_hover_time) \ tme.cbSize = sizeof(tme); \ tme.dwFlags = TME_HOVER; \ tme.hwndTrack = track_hwnd; \ tme.dwHoverTime = track_hover_time; \ SetLastError(0xdeadbeef); \ ret = pTrackMouseEvent(&tme); \ ok(ret, "TrackMouseEvent(TME_HOVER) error %d\n", GetLastError())
#define track_query(expected_track_flags, expected_track_hwnd, expected_hover_time) \ tme.cbSize = sizeof(tme); \ tme.dwFlags = TME_QUERY; \ tme.hwndTrack = (HWND)0xdeadbeef; \ tme.dwHoverTime = 0xdeadbeef; \ SetLastError(0xdeadbeef); \ ret = pTrackMouseEvent(&tme); \ ok(ret, "TrackMouseEvent(TME_QUERY) error %d\n", GetLastError());\ ok(tme.cbSize == sizeof(tme), "wrong tme.cbSize %u\n", tme.cbSize); \ ok(tme.dwFlags == (expected_track_flags), \ "wrong tme.dwFlags %08x, expected %08x\n", tme.dwFlags, (expected_track_flags)); \ ok(tme.hwndTrack == (expected_track_hwnd), \ "wrong tme.hwndTrack %p, expected %p\n", tme.hwndTrack, (expected_track_hwnd)); \ ok(tme.dwHoverTime == (expected_hover_time), \ "wrong tme.dwHoverTime %u, expected %u\n", tme.dwHoverTime, (expected_hover_time))
#define track_hover_cancel(track_hwnd) \ tme.cbSize = sizeof(tme); \ tme.dwFlags = TME_HOVER | TME_CANCEL; \ tme.hwndTrack = track_hwnd; \ tme.dwHoverTime = 0xdeadbeef; \ SetLastError(0xdeadbeef); \ ret = pTrackMouseEvent(&tme); \ ok(ret, "TrackMouseEvent(TME_HOVER | TME_CANCEL) error %d\n", GetLastError())
default_hover_time = 0xdeadbeef; SetLastError(0xdeadbeef); ret = SystemParametersInfoA(SPI_GETMOUSEHOVERTIME, 0, &default_hover_time, 0); ok(ret || broken(GetLastError() == 0xdeadbeef), /* win9x */ "SystemParametersInfo(SPI_GETMOUSEHOVERTIME) error %u\n", GetLastError()); if (!ret) default_hover_time = 400; trace("SPI_GETMOUSEHOVERTIME returned %u ms\n", default_hover_time);
SetLastError(0xdeadbeef); ret = SystemParametersInfoA(SPI_GETMOUSEHOVERWIDTH, 0, &hover_width, 0); ok(ret || broken(GetLastError() == 0xdeadbeef), /* win9x */ "SystemParametersInfo(SPI_GETMOUSEHOVERWIDTH) error %u\n", GetLastError()); if (!ret) hover_width = 4; SetLastError(0xdeadbeef); ret = SystemParametersInfoA(SPI_GETMOUSEHOVERHEIGHT, 0, &hover_height, 0); ok(ret || broken(GetLastError() == 0xdeadbeef), /* win9x */ "SystemParametersInfo(SPI_GETMOUSEHOVERHEIGHT) error %u\n", GetLastError()); if (!ret) hover_height = 4; trace("hover rect is %u x %d\n", hover_width, hover_height);
hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0, NULL, NULL, 0); assert(hwnd);
hchild = CreateWindowExA(0, "TestWindowClass", NULL, WS_CHILD | WS_BORDER | WS_VISIBLE, 50, 50, 200, 200, hwnd, NULL, NULL, 0); assert(hchild);
SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE ); flush_events(); flush_sequence();
tme.cbSize = 0; tme.dwFlags = TME_QUERY; tme.hwndTrack = (HWND)0xdeadbeef; tme.dwHoverTime = 0xdeadbeef; SetLastError(0xdeadbeef); ret = pTrackMouseEvent(&tme); ok(!ret, "TrackMouseEvent should fail\n"); ok(GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == 0xdeadbeef), "not expected error %u\n", GetLastError());
tme.cbSize = sizeof(tme); tme.dwFlags = TME_HOVER; tme.hwndTrack = (HWND)0xdeadbeef; tme.dwHoverTime = 0xdeadbeef; SetLastError(0xdeadbeef); ret = pTrackMouseEvent(&tme); ok(!ret, "TrackMouseEvent should fail\n"); ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || broken(GetLastError() == 0xdeadbeef), "not expected error %u\n", GetLastError());
tme.cbSize = sizeof(tme); tme.dwFlags = TME_HOVER | TME_CANCEL; tme.hwndTrack = (HWND)0xdeadbeef; tme.dwHoverTime = 0xdeadbeef; SetLastError(0xdeadbeef); ret = pTrackMouseEvent(&tme); ok(!ret, "TrackMouseEvent should fail\n"); ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || broken(GetLastError() == 0xdeadbeef), "not expected error %u\n", GetLastError());
GetWindowRect(hwnd, &rc_parent); GetWindowRect(hchild, &rc_child); SetCursorPos(rc_child.left - 10, rc_child.top - 10);
/* Process messages so that the system updates its internal current * window and hittest, otherwise TrackMouseEvent calls don't have any * effect. */ flush_events(); flush_sequence();
track_query(0, NULL, 0); track_hover(hchild, 0); track_query(0, NULL, 0);
flush_events(); flush_sequence();
track_hover(hwnd, 0); tme.cbSize = sizeof(tme); tme.dwFlags = TME_QUERY; tme.hwndTrack = (HWND)0xdeadbeef; tme.dwHoverTime = 0xdeadbeef; SetLastError(0xdeadbeef); ret = pTrackMouseEvent(&tme); ok(ret, "TrackMouseEvent(TME_QUERY) error %d\n", GetLastError()); ok(tme.cbSize == sizeof(tme), "wrong tme.cbSize %u\n", tme.cbSize); if (!tme.dwFlags) { skip( "Cursor not inside window, skipping TrackMouseEvent tests\n" ); DestroyWindow( hwnd ); return; } ok(tme.dwFlags == TME_HOVER, "wrong tme.dwFlags %08x, expected TME_HOVER\n", tme.dwFlags); ok(tme.hwndTrack == hwnd, "wrong tme.hwndTrack %p, expected %p\n", tme.hwndTrack, hwnd); ok(tme.dwHoverTime == default_hover_time, "wrong tme.dwHoverTime %u, expected %u\n", tme.dwHoverTime, default_hover_time);
pump_msg_loop_timeout(default_hover_time, FALSE); ok_sequence(WmMouseHoverSeq, "WmMouseHoverSeq", FALSE);
track_query(0, NULL, 0);
track_hover(hwnd, HOVER_DEFAULT); track_query(TME_HOVER, hwnd, default_hover_time);
Sleep(default_hover_time / 2); mouse_event(MOUSEEVENTF_MOVE, -1, 0, 0, 0); mouse_event(MOUSEEVENTF_MOVE, 1, 0, 0, 0);
track_query(TME_HOVER, hwnd, default_hover_time);
pump_msg_loop_timeout(default_hover_time, FALSE); ok_sequence(WmMouseHoverSeq, "WmMouseHoverSeq", FALSE);
track_query(0, NULL, 0);
track_hover(hwnd, HOVER_DEFAULT); track_query(TME_HOVER, hwnd, default_hover_time);
pump_msg_loop_timeout(default_hover_time, TRUE); ok_sequence(WmMouseHoverSeq, "WmMouseHoverSeq", FALSE);
track_query(0, NULL, 0);
track_hover(hwnd, HOVER_DEFAULT); track_query(TME_HOVER, hwnd, default_hover_time); track_hover_cancel(hwnd);
DestroyWindow(hwnd);
#undef track_hover#undef track_query#undef track_hover_cancel}
static const struct message WmSetWindowRgn[] = { { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCCALCSIZE, sent|wparam, 1 }, { WM_NCPAINT, sent|optional }, /* wparam != 1 */ { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { 0 }};
static const struct message WmSetWindowRgn_no_redraw[] = { { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW }, { WM_NCCALCSIZE, sent|wparam, 1 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { 0 }};
static const struct message WmSetWindowRgn_clear[] = { { WM_WINDOWPOSCHANGING, sent/*|wparam*/, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE/*|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE only on some Windows versions */ }, { WM_NCCALCSIZE, sent|wparam, 1 }, { WM_NCPAINT, sent|optional }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent|optional }, /* FIXME: remove optional once Wine is fixed */ { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCCALCSIZE, sent|wparam|optional, 1 }, { WM_NCPAINT, sent|optional }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent|optional }, { WM_WINDOWPOSCHANGING, sent|optional }, { WM_NCCALCSIZE, sent|optional|wparam, 1 }, { WM_NCPAINT, sent|optional }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent|optional }, { WM_WINDOWPOSCHANGED, sent|optional|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCCALCSIZE, sent|optional|wparam, 1 }, { WM_NCPAINT, sent|optional }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent|optional }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { 0 }};
static void test_SetWindowRgn(void){ HRGN hrgn; HWND hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW, 100, 100, 200, 200, 0, 0, 0, NULL); ok( hwnd != 0, "Failed to create overlapped window\n" );
ShowWindow( hwnd, SW_SHOW ); UpdateWindow( hwnd ); flush_events(); flush_sequence();
trace("testing SetWindowRgn\n"); hrgn = CreateRectRgn( 0, 0, 150, 150 ); SetWindowRgn( hwnd, hrgn, TRUE ); ok_sequence( WmSetWindowRgn, "WmSetWindowRgn", FALSE );
hrgn = CreateRectRgn( 30, 30, 160, 160 ); SetWindowRgn( hwnd, hrgn, FALSE ); ok_sequence( WmSetWindowRgn_no_redraw, "WmSetWindowRgn_no_redraw", FALSE );
hrgn = CreateRectRgn( 0, 0, 180, 180 ); SetWindowRgn( hwnd, hrgn, TRUE ); ok_sequence( WmSetWindowRgn, "WmSetWindowRgn2", FALSE );
SetWindowRgn( hwnd, 0, TRUE ); ok_sequence( WmSetWindowRgn_clear, "WmSetWindowRgn_clear", FALSE );
DestroyWindow( hwnd );}
/*************************** ShowWindow() test ******************************/static const struct message WmShowNormal[] = { { WM_SHOWWINDOW, sent|wparam, 1 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, { HCBT_ACTIVATE, hook }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2003 doesn't send it */ { HCBT_SETFOCUS, hook }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { 0 }};static const struct message WmShow[] = { { WM_SHOWWINDOW, sent|wparam, 1 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, { HCBT_ACTIVATE, hook|optional }, /* win2000 doesn't send it */ { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2000 doesn't send it */ { HCBT_SETFOCUS, hook|optional }, /* win2000 doesn't send it */ { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { 0 }};static const struct message WmShowNoActivate_1[] = { { HCBT_MINMAX, hook|lparam, 0, SW_SHOWNOACTIVATE }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_STATECHANGED, 0, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOSIZE|SWP_NOMOVE }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_STATECHANGED, 0, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOSIZE|SWP_NOMOVE }, { WM_MOVE, sent|defwinproc|optional }, { WM_SIZE, sent|wparam|defwinproc, SIZE_RESTORED }, { 0 }};static const struct message WmShowNoActivate_2[] = { { HCBT_MINMAX, hook|lparam, 0, SW_SHOWNOACTIVATE }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED, 0, SWP_NOACTIVATE }, { HCBT_ACTIVATE, hook|optional }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, { HCBT_SETFOCUS, hook|optional }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED, 0, SWP_NOACTIVATE }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|wparam|defwinproc, SIZE_RESTORED }, { HCBT_SETFOCUS, hook|optional }, { HCBT_ACTIVATE, hook|optional }, /* win2003 doesn't send it */ { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2003 doesn't send it */ { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { HCBT_SETFOCUS, hook|optional }, /* win2003 doesn't send it */ { 0 }};static const struct message WmShowNA_1[] = { { WM_SHOWWINDOW, sent|wparam, 1 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { 0 }};static const struct message WmShowNA_2[] = { { WM_SHOWWINDOW, sent|wparam, 1 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { 0 }};static const struct message WmRestore_1[] = { { HCBT_MINMAX, hook|lparam, 0, SW_RESTORE }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, { HCBT_ACTIVATE, hook|optional }, /* win2000 doesn't send it */ { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2000 doesn't send it */ { HCBT_SETFOCUS, hook|optional }, /* win2000 doesn't send it */ { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|wparam|defwinproc, SIZE_RESTORED }, { HCBT_SETFOCUS, hook|optional }, /* win2000 sends it */ { 0 }};static const struct message WmRestore_2[] = { { WM_SHOWWINDOW, sent|wparam, 1 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, { HCBT_ACTIVATE, hook|optional }, /* win2000 doesn't send it */ { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2000 doesn't send it */ { HCBT_SETFOCUS, hook|optional }, /* win2000 doesn't send it */ { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { 0 }};static const struct message WmRestore_3[] = { { HCBT_MINMAX, hook|lparam, 0, SW_RESTORE }, { WM_GETMINMAXINFO, sent }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, { HCBT_ACTIVATE, hook|optional }, /* win2003 doesn't send it */ { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2003 doesn't send it */ { HCBT_SETFOCUS, hook|optional }, /* win2003 doesn't send it */ { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|wparam|defwinproc, SIZE_MAXIMIZED }, { HCBT_SETFOCUS, hook|optional }, /* win2003 sends it */ { 0 }};static const struct message WmRestore_4[] = { { HCBT_MINMAX, hook|lparam|optional, 0, SW_RESTORE }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_FRAMECHANGED|SWP_STATECHANGED, 0, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOSIZE|SWP_NOMOVE }, { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_FRAMECHANGED|SWP_STATECHANGED, 0, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOSIZE|SWP_NOMOVE }, { WM_MOVE, sent|defwinproc|optional }, { WM_SIZE, sent|wparam|defwinproc|optional, SIZE_RESTORED }, { 0 }};static const struct message WmRestore_5[] = { { HCBT_MINMAX, hook|lparam|optional, 0, SW_SHOWNORMAL }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_FRAMECHANGED|SWP_STATECHANGED, 0, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOSIZE|SWP_NOMOVE }, { HCBT_ACTIVATE, hook|optional }, { HCBT_SETFOCUS, hook|optional }, { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_FRAMECHANGED|SWP_STATECHANGED, 0, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOSIZE|SWP_NOMOVE }, { WM_MOVE, sent|defwinproc|optional }, { WM_SIZE, sent|wparam|defwinproc|optional, SIZE_RESTORED }, { 0 }};static const struct message WmHide_1[] = { { WM_SHOWWINDOW, sent|wparam, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE, 0, SWP_NOACTIVATE }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE, 0, SWP_NOACTIVATE }, { HCBT_ACTIVATE, hook|optional }, { HCBT_SETFOCUS, hook|optional }, /* win2000 sends it */ { 0 }};static const struct message WmHide_2[] = { { WM_SHOWWINDOW, sent|wparam, 0 }, { WM_WINDOWPOSCHANGING, sent /*|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE*/ }, /* win2000 doesn't add SWP_NOACTIVATE */ { WM_WINDOWPOSCHANGED, sent /*|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ }, /* win2000 doesn't add SWP_NOACTIVATE */ { HCBT_ACTIVATE, hook|optional }, { 0 }};static const struct message WmHide_3[] = { { WM_SHOWWINDOW, sent|wparam, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { HCBT_SETFOCUS, hook|optional }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { 0 }};static const struct message WmShowMinimized_1[] = { { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINIMIZED }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, { HCBT_ACTIVATE, hook|optional }, /* win2000 doesn't send it */ { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2000 doesn't send it */ { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|wparam|lparam|defwinproc, SIZE_MINIMIZED, 0 }, { 0 }};static const struct message WmMinimize_1[] = { { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE }, { HCBT_SETFOCUS, hook|optional }, /* win2000 doesn't send it */ { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|wparam|lparam|defwinproc, SIZE_MINIMIZED, 0 }, { 0 }};static const struct message WmMinimize_2[] = { { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE }, { HCBT_SETFOCUS, hook|optional }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED, 0, SWP_NOACTIVATE }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED, 0, SWP_NOACTIVATE }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|wparam|lparam|defwinproc, SIZE_MINIMIZED, 0 }, { 0 }};static const struct message WmMinimize_3[] = { { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED, 0, SWP_NOACTIVATE }, { HCBT_ACTIVATE, hook|optional }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED, 0, SWP_NOACTIVATE }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|wparam|lparam|defwinproc, SIZE_MINIMIZED, 0 }, { 0 }};static const struct message WmShowMinNoActivate[] = { { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINNOACTIVE }, { WM_WINDOWPOSCHANGING, sent }, { WM_WINDOWPOSCHANGED, sent }, { WM_MOVE, sent|defwinproc|optional }, { WM_SIZE, sent|wparam|lparam|defwinproc|optional, SIZE_MINIMIZED, 0 }, { 0 }};static const struct message WmMinMax_1[] = { { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINIMIZED }, { 0 }};static const struct message WmMinMax_2[] = { { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMAXIMIZED }, { WM_GETMINMAXINFO, sent|optional }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_FRAMECHANGED|SWP_STATECHANGED }, { HCBT_ACTIVATE, hook|optional }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, { HCBT_SETFOCUS, hook|optional }, { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_FRAMECHANGED|SWP_STATECHANGED, 0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { WM_MOVE, sent|defwinproc|optional }, { WM_SIZE, sent|wparam|defwinproc|optional, SIZE_MAXIMIZED }, { HCBT_SETFOCUS, hook|optional }, { 0 }};static const struct message WmMinMax_3[] = { { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE }, { HCBT_SETFOCUS, hook|optional }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, { WM_MOVE, sent|defwinproc|optional }, { WM_SIZE, sent|wparam|lparam|defwinproc|optional, SIZE_MINIMIZED, 0 }, { 0 }};static const struct message WmMinMax_4[] = { { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINNOACTIVE }, { 0 }};static const struct message WmShowMaximized_1[] = { { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMAXIMIZED }, { WM_GETMINMAXINFO, sent }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, { HCBT_ACTIVATE, hook|optional }, /* win2000 doesn't send it */ { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2000 doesn't send it */ { HCBT_SETFOCUS, hook|optional }, /* win2000 doesn't send it */ { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|wparam|defwinproc, SIZE_MAXIMIZED }, { HCBT_SETFOCUS, hook|optional }, /* win2003 sends it */ { 0 }};static const struct message WmShowMaximized_2[] = { { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMAXIMIZED }, { WM_GETMINMAXINFO, sent }, { WM_WINDOWPOSCHANGING, sent|optional }, { HCBT_ACTIVATE, hook|optional }, { WM_WINDOWPOSCHANGED, sent|optional }, { WM_MOVE, sent|optional }, /* Win9x doesn't send it */ { WM_SIZE, sent|wparam|optional, SIZE_MAXIMIZED }, /* Win9x doesn't send it */ { WM_WINDOWPOSCHANGING, sent|optional }, { HCBT_SETFOCUS, hook|optional }, { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|wparam|defwinproc, SIZE_MAXIMIZED }, { HCBT_SETFOCUS, hook|optional }, { 0 }};static const struct message WmShowMaximized_3[] = { { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMAXIMIZED }, { WM_GETMINMAXINFO, sent|optional }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED, 0, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOSIZE|SWP_NOMOVE }, { HCBT_ACTIVATE, hook|optional }, /* win2000 doesn't send it */ { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2000 doesn't send it */ { HCBT_SETFOCUS, hook|optional }, /* win2000 doesn't send it */ { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED, 0, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOSIZE|SWP_NOMOVE }, { WM_MOVE, sent|defwinproc|optional }, { WM_SIZE, sent|wparam|defwinproc, SIZE_MAXIMIZED }, { 0 }};
static void test_ShowWindow(void){ /* ShowWindow commands in random order */ static const struct { INT cmd; /* ShowWindow command */ LPARAM ret; /* ShowWindow return value */ DWORD style; /* window style after the command */ const struct message *msg; /* message sequence the command produces */ INT wp_cmd, wp_flags; /* window placement after the command */ POINT wp_min, wp_max; /* window placement after the command */ BOOL todo_msg; /* message sequence doesn't match what Wine does */ } sw[] = {/* 1 */ { SW_SHOWNORMAL, FALSE, WS_VISIBLE, WmShowNormal, SW_SHOWNORMAL, 0, {-1,-1}, {-1,-1}, FALSE },/* 2 */ { SW_SHOWNORMAL, TRUE, WS_VISIBLE, WmEmptySeq, SW_SHOWNORMAL, 0, {-1,-1}, {-1,-1}, FALSE },/* 3 */ { SW_HIDE, TRUE, 0, WmHide_1, SW_SHOWNORMAL, 0, {-1,-1}, {-1,-1}, FALSE },/* 4 */ { SW_HIDE, FALSE, 0, WmEmptySeq, SW_SHOWNORMAL, 0, {-1,-1}, {-1,-1}, FALSE },/* 5 */ { SW_SHOWMINIMIZED, FALSE, WS_VISIBLE|WS_MINIMIZE, WmShowMinimized_1, SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE },/* 6 */ { SW_SHOWMINIMIZED, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_1, SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE },/* 7 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_1, SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE },/* 8 */ { SW_HIDE, FALSE, WS_MINIMIZE, WmEmptySeq, SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE },/* 9 */ { SW_SHOWMAXIMIZED, FALSE, WS_VISIBLE|WS_MAXIMIZE, WmShowMaximized_1, SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE },/* 10 */ { SW_SHOWMAXIMIZED, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmMinMax_2, SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE },/* 11 */ { SW_HIDE, TRUE, WS_MAXIMIZE, WmHide_1, SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE },/* 12 */ { SW_HIDE, FALSE, WS_MAXIMIZE, WmEmptySeq, SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE },/* 13 */ { SW_SHOWNOACTIVATE, FALSE, WS_VISIBLE, WmShowNoActivate_1, SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE },/* 14 */ { SW_SHOWNOACTIVATE, TRUE, WS_VISIBLE, WmEmptySeq, SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE },/* 15 */ { SW_HIDE, TRUE, 0, WmHide_2, SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE },/* 16 */ { SW_HIDE, FALSE, 0, WmEmptySeq, SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE },/* 17 */ { SW_SHOW, FALSE, WS_VISIBLE, WmShow, SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE },/* 18 */ { SW_SHOW, TRUE, WS_VISIBLE, WmEmptySeq, SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE },/* 19 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinimize_1, SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE },/* 20 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_3, SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE },/* 21 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_2, SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE },/* 22 */ { SW_SHOWMINNOACTIVE, FALSE, WS_VISIBLE|WS_MINIMIZE, WmShowMinNoActivate, SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, TRUE },/* 23 */ { SW_SHOWMINNOACTIVE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_4, SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE },/* 24 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_2, SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE },/* 25 */ { SW_HIDE, FALSE, WS_MINIMIZE, WmEmptySeq, SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE },/* 26 */ { SW_SHOWNA, FALSE, WS_VISIBLE|WS_MINIMIZE, WmShowNA_1, SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE },/* 27 */ { SW_SHOWNA, TRUE, WS_VISIBLE|WS_MINIMIZE, WmShowNA_2, SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE },/* 28 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_2, SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE },/* 29 */ { SW_HIDE, FALSE, WS_MINIMIZE, WmEmptySeq, SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE },/* 30 */ { SW_RESTORE, FALSE, WS_VISIBLE, WmRestore_1, SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE },/* 31 */ { SW_RESTORE, TRUE, WS_VISIBLE, WmEmptySeq, SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE },/* 32 */ { SW_HIDE, TRUE, 0, WmHide_3, SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE },/* 33 */ { SW_HIDE, FALSE, 0, WmEmptySeq, SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE },/* 34 */ { SW_NORMALNA, FALSE, 0, WmEmptySeq, /* what does this mean?! */ SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE },/* 35 */ { SW_NORMALNA, FALSE, 0, WmEmptySeq, SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE },/* 36 */ { SW_HIDE, FALSE, 0, WmEmptySeq, SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE },/* 37 */ { SW_RESTORE, FALSE, WS_VISIBLE, WmRestore_2, SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE },/* 38 */ { SW_RESTORE, TRUE, WS_VISIBLE, WmEmptySeq, SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE },/* 39 */ { SW_SHOWNOACTIVATE, TRUE, WS_VISIBLE, WmEmptySeq, SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE },/* 40 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinimize_2, SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE },/* 41 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_3, SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE },/* 42 */ { SW_SHOWMAXIMIZED, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmShowMaximized_2, SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE },/* 43 */ { SW_SHOWMAXIMIZED, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmMinMax_2, SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE },/* 44 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinimize_1, SW_SHOWMINIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE },/* 45 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_3, SW_SHOWMINIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE },/* 46 */ { SW_RESTORE, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmRestore_3, SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE },/* 47 */ { SW_RESTORE, TRUE, WS_VISIBLE, WmRestore_4, SW_SHOWNORMAL, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE },/* 48 */ { SW_SHOWMAXIMIZED, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmShowMaximized_3, SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE },/* 49 */ { SW_SHOW, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmEmptySeq, SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE },/* 50 */ { SW_SHOWNORMAL, TRUE, WS_VISIBLE, WmRestore_5, SW_SHOWNORMAL, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE },/* 51 */ { SW_SHOWNORMAL, TRUE, WS_VISIBLE, WmRestore_5, SW_SHOWNORMAL, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE },/* 52 */ { SW_HIDE, TRUE, 0, WmHide_1, SW_SHOWNORMAL, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE },/* 53 */ { SW_HIDE, FALSE, 0, WmEmptySeq, SW_SHOWNORMAL, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE },/* 54 */ { SW_MINIMIZE, FALSE, WS_VISIBLE|WS_MINIMIZE, WmMinimize_3, SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE },/* 55 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_2, SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE },/* 56 */ { SW_SHOWNOACTIVATE, FALSE, WS_VISIBLE, WmShowNoActivate_2, SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE },/* 57 */ { SW_SHOW, TRUE, WS_VISIBLE, WmEmptySeq, SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE } }; HWND hwnd; DWORD style; LPARAM ret; INT i; WINDOWPLACEMENT wp; RECT win_rc, work_rc = {0, 0, 0, 0};
#define WS_BASE (WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_POPUP|WS_CLIPSIBLINGS) hwnd = CreateWindowExA(0, "ShowWindowClass", NULL, WS_BASE, 120, 120, 90, 90, 0, 0, 0, NULL); assert(hwnd);
style = GetWindowLongA(hwnd, GWL_STYLE) & ~WS_BASE; ok(style == 0, "expected style 0, got %08x\n", style);
flush_events(); flush_sequence();
if (pGetMonitorInfoA && pMonitorFromPoint) { HMONITOR hmon; MONITORINFO mi; POINT pt = {0, 0};
SetLastError(0xdeadbeef); hmon = pMonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY); ok(hmon != 0, "MonitorFromPoint error %u\n", GetLastError());
mi.cbSize = sizeof(mi); SetLastError(0xdeadbeef); ret = pGetMonitorInfoA(hmon, &mi); ok(ret, "GetMonitorInfo error %u\n", GetLastError()); trace("monitor %s, work %s\n", wine_dbgstr_rect(&mi.rcMonitor), wine_dbgstr_rect(&mi.rcWork)); work_rc = mi.rcWork; }
GetWindowRect(hwnd, &win_rc); OffsetRect(&win_rc, -work_rc.left, -work_rc.top);
wp.length = sizeof(wp); SetLastError(0xdeadbeaf); ret = GetWindowPlacement(hwnd, &wp); ok(ret, "GetWindowPlacement error %u\n", GetLastError()); ok(wp.flags == 0, "expected 0, got %#x\n", wp.flags); ok(wp.showCmd == SW_SHOWNORMAL, "expected SW_SHOWNORMAL, got %d\n", wp.showCmd); ok(wp.ptMinPosition.x == -1 && wp.ptMinPosition.y == -1, "expected -1,-1 got %d,%d\n", wp.ptMinPosition.x, wp.ptMinPosition.y); ok(wp.ptMaxPosition.x == -1 && wp.ptMaxPosition.y == -1, "expected -1,-1 got %d,%d\n", wp.ptMaxPosition.x, wp.ptMaxPosition.y); todo_wine_if (work_rc.left || work_rc.top) /* FIXME: remove once Wine is fixed */ ok(EqualRect(&win_rc, &wp.rcNormalPosition), "expected %s got %s\n", wine_dbgstr_rect(&win_rc), wine_dbgstr_rect(&wp.rcNormalPosition));
for (i = 0; i < ARRAY_SIZE(sw); i++) { static const char * const sw_cmd_name[13] = { "SW_HIDE", "SW_SHOWNORMAL", "SW_SHOWMINIMIZED", "SW_SHOWMAXIMIZED", "SW_SHOWNOACTIVATE", "SW_SHOW", "SW_MINIMIZE", "SW_SHOWMINNOACTIVE", "SW_SHOWNA", "SW_RESTORE", "SW_SHOWDEFAULT", "SW_FORCEMINIMIZE", "SW_NORMALNA" /* 0xCC */ }; char comment[64]; INT idx; /* index into the above array of names */
idx = (sw[i].cmd == SW_NORMALNA) ? 12 : sw[i].cmd;
style = GetWindowLongA(hwnd, GWL_STYLE); trace("%d: sending %s, current window style %08x\n", i+1, sw_cmd_name[idx], style); ret = ShowWindow(hwnd, sw[i].cmd); ok(!ret == !sw[i].ret, "%d: cmd %s: expected ret %lu, got %lu\n", i+1, sw_cmd_name[idx], sw[i].ret, ret); style = GetWindowLongA(hwnd, GWL_STYLE) & ~WS_BASE; ok(style == sw[i].style, "%d: expected style %08x, got %08x\n", i+1, sw[i].style, style);
sprintf(comment, "%d: ShowWindow(%s)", i+1, sw_cmd_name[idx]); ok_sequence(sw[i].msg, comment, sw[i].todo_msg);
wp.length = sizeof(wp); SetLastError(0xdeadbeaf); ret = GetWindowPlacement(hwnd, &wp); ok(ret, "GetWindowPlacement error %u\n", GetLastError()); ok(wp.flags == sw[i].wp_flags, "expected %#x, got %#x\n", sw[i].wp_flags, wp.flags); ok(wp.showCmd == sw[i].wp_cmd, "expected %d, got %d\n", sw[i].wp_cmd, wp.showCmd);
/* NT moves the minimized window to -32000,-32000, win9x to 3000,3000 */ if ((wp.ptMinPosition.x + work_rc.left == -32000 && wp.ptMinPosition.y + work_rc.top == -32000) || (wp.ptMinPosition.x + work_rc.left == 3000 && wp.ptMinPosition.y + work_rc.top == 3000)) { ok((wp.ptMinPosition.x + work_rc.left == sw[i].wp_min.x && wp.ptMinPosition.y + work_rc.top == sw[i].wp_min.y) || (wp.ptMinPosition.x + work_rc.left == 3000 && wp.ptMinPosition.y + work_rc.top == 3000), "expected %d,%d got %d,%d\n", sw[i].wp_min.x, sw[i].wp_min.y, wp.ptMinPosition.x, wp.ptMinPosition.y); } else { ok(wp.ptMinPosition.x == sw[i].wp_min.x && wp.ptMinPosition.y == sw[i].wp_min.y, "expected %d,%d got %d,%d\n", sw[i].wp_min.x, sw[i].wp_min.y, wp.ptMinPosition.x, wp.ptMinPosition.y); }
todo_wine_if(wp.ptMaxPosition.x != sw[i].wp_max.x || wp.ptMaxPosition.y != sw[i].wp_max.y) ok(wp.ptMaxPosition.x == sw[i].wp_max.x && wp.ptMaxPosition.y == sw[i].wp_max.y, "expected %d,%d got %d,%d\n", sw[i].wp_max.x, sw[i].wp_max.y, wp.ptMaxPosition.x, wp.ptMaxPosition.y);
if (0) /* FIXME: Wine behaves completely different here */ ok(EqualRect(&win_rc, &wp.rcNormalPosition), "expected %s got %s\n", wine_dbgstr_rect(&win_rc), wine_dbgstr_rect(&wp.rcNormalPosition)); } DestroyWindow(hwnd); flush_events();}
static INT_PTR WINAPI test_dlg_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ struct recvd_message msg;
if (ignore_message( message )) return 0;
msg.hwnd = hwnd; msg.message = message; msg.flags = sent|wparam|lparam; msg.wParam = wParam; msg.lParam = lParam; msg.descr = "dialog"; add_message(&msg);
/* calling DefDlgProc leads to a recursion under XP */
switch (message) { case WM_INITDIALOG: return lParam;
case WM_GETDLGCODE: return 0; } return 1;}
static WNDPROC orig_edit_proc;static LRESULT WINAPI dlg_creation_edit_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp){ struct recvd_message msg;
if (ignore_message( message )) return 0;
msg.hwnd = hwnd; msg.message = message; msg.flags = sent|wparam|lparam; msg.wParam = wp; msg.lParam = lp; msg.descr = "edit"; add_message(&msg);
return CallWindowProcW(orig_edit_proc, hwnd, message, wp, lp);}
static INT_PTR WINAPI test_dlg_proc2(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ struct recvd_message msg;
if (ignore_message( message )) return 0;
msg.hwnd = hwnd; msg.message = message; msg.flags = sent|wparam|lparam|parent; msg.wParam = wParam; msg.lParam = lParam; msg.descr = "dialog"; add_message(&msg);
if (message == WM_INITDIALOG) { orig_edit_proc = (WNDPROC)SetWindowLongPtrW(GetDlgItem(hwnd, 200), GWLP_WNDPROC, (LONG_PTR)dlg_creation_edit_proc); }
return 1;}
static INT_PTR WINAPI test_dlg_proc3(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ ok( 0, "should not be called since DefDlgProc is not used\n" ); return 0;}
static LRESULT WINAPI test_dlg_proc4(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ struct recvd_message msg;
if (!ignore_message( message )) { msg.hwnd = hwnd; msg.message = message; msg.flags = sent|wparam|lparam|parent; msg.wParam = wParam; msg.lParam = lParam; msg.descr = "dialog"; add_message(&msg); } if (message == WM_INITDIALOG) { orig_edit_proc = (WNDPROC)SetWindowLongPtrW(GetDlgItem(hwnd, 200), GWLP_WNDPROC, (LONG_PTR)dlg_creation_edit_proc); return 1; } return DefWindowProcW( hwnd, message, wParam, lParam );}
static const struct message WmDefDlgSetFocus_1[] = { { WM_GETDLGCODE, sent|wparam|lparam, 0, 0 }, { WM_GETTEXTLENGTH, sent|wparam|lparam|optional, 0, 0 }, /* XP */ { WM_GETTEXT, sent|wparam|optional, 6 }, /* XP */ { WM_GETTEXT, sent|wparam|optional, 12 }, /* XP */ { EM_SETSEL, sent|wparam, 0 }, /* XP sets lparam to text length, Win9x to -2 */ { HCBT_SETFOCUS, hook }, { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|wparam, 0 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 10 }, { WM_CTLCOLOREDIT, sent }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 11 }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, { WM_COMMAND, sent|wparam, MAKEWPARAM(1, EN_SETFOCUS) }, { 0 }};static const struct message WmDefDlgSetFocus_2[] = { { WM_GETDLGCODE, sent|wparam|lparam, 0, 0 }, { WM_GETTEXTLENGTH, sent|wparam|lparam|optional, 0, 0 }, /* XP */ { WM_GETTEXT, sent|wparam|optional, 6 }, /* XP */ { WM_GETTEXT, sent|wparam|optional, 12 }, /* XP */ { EM_SETSEL, sent|wparam, 0 }, /* XP sets lparam to text length, Win9x to -2 */ { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, { WM_CTLCOLOREDIT, sent|optional }, /* XP */ { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, { 0 }};/* Creation of a dialog */static const struct message WmCreateDialogParamSeq_0[] = { { HCBT_CREATEWND, hook }, { WM_NCCREATE, sent }, { WM_NCCALCSIZE, sent|wparam, 0 }, { WM_CREATE, sent }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SIZE, sent|wparam, SIZE_RESTORED }, { WM_MOVE, sent }, { WM_SETFONT, sent }, { WM_INITDIALOG, sent }, { WM_CHANGEUISTATE, sent|optional }, { 0 }};/* Creation of a dialog */static const struct message WmCreateDialogParamSeq_1[] = { { HCBT_CREATEWND, hook }, { WM_NCCREATE, sent }, { WM_NCCALCSIZE, sent|wparam, 0 }, { WM_CREATE, sent }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SIZE, sent|wparam, SIZE_RESTORED }, { WM_MOVE, sent }, { WM_SETFONT, sent }, { WM_INITDIALOG, sent }, { WM_GETDLGCODE, sent|wparam|lparam|optional, 0, 0 }, /* FIXME: Wine doesn't send it */ { HCBT_SETFOCUS, hook }, { HCBT_ACTIVATE, hook }, { WM_QUERYNEWPALETTE, sent|optional }, { WM_PALETTEISCHANGING, sent|optional }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, { WM_ACTIVATEAPP, sent|wparam, 1 }, { WM_NCACTIVATE, sent }, { WM_ACTIVATE, sent|wparam, 1 }, { WM_SETFOCUS, sent }, { WM_CHANGEUISTATE, sent|optional }, { 0 }};/* Creation of a dialog */static const struct message WmCreateDialogParamSeq_2[] = { { HCBT_CREATEWND, hook }, { WM_NCCREATE, sent }, { WM_NCCALCSIZE, sent|wparam, 0 }, { WM_CREATE, sent }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SIZE, sent|wparam, SIZE_RESTORED }, { WM_MOVE, sent }, { WM_CHANGEUISTATE, sent|optional }, { 0 }};
static const struct message WmCreateDialogParamSeq_3[] = { { HCBT_CREATEWND, hook }, { WM_SETFONT, sent|parent }, { WM_INITDIALOG, sent|parent }, { WM_GETDLGCODE, sent|wparam|lparam, 0, 0 }, { EM_SETSEL, sent|wparam|lparam, 0, INT_MAX }, { EM_SETSEL, sent|wparam|lparam|optional, 0, INT_MAX }, { EM_SETSEL, sent|wparam|lparam|optional, 0, INT_MAX }, { EM_SETSEL, sent|wparam|lparam|optional, 0, INT_MAX }, { HCBT_ACTIVATE, hook }, { WM_QUERYNEWPALETTE, sent|parent|optional }, /* TODO: this message should not be sent */ { WM_WINDOWPOSCHANGING, sent|parent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, { WM_WINDOWPOSCHANGING, sent|parent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, { WM_WINDOWPOSCHANGED, sent|parent|wparam|optional, SWP_NOREDRAW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { WM_WINDOWPOSCHANGED, sent|parent|wparam|optional, SWP_NOREDRAW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { WM_ACTIVATEAPP, sent|parent|wparam, 1 }, { WM_NCACTIVATE, sent|parent }, { WM_ACTIVATE, sent|parent|wparam, 1 }, { WM_SETFOCUS, sent }, { WM_COMMAND, sent|parent|wparam, MAKELONG(200, EN_SETFOCUS) }, { WM_GETDLGCODE, sent|wparam|lparam, 0, 0 }, { WM_USER, sent|parent }, { WM_CHANGEUISTATE, sent|parent|optional }, { 0 }};
static const struct message WmCreateDialogParamSeq_4[] = { { HCBT_CREATEWND, hook }, { WM_NCCREATE, sent|parent }, { WM_NCCALCSIZE, sent|parent|wparam, 0 }, { WM_CREATE, sent|parent }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SIZE, sent|parent|wparam, SIZE_RESTORED }, { WM_MOVE, sent|parent }, { WM_SETFONT, sent|parent }, { WM_INITDIALOG, sent|parent }, { WM_GETDLGCODE, sent|wparam|lparam, 0, 0 }, { EM_SETSEL, sent|wparam|lparam, 0, INT_MAX }, { EM_SETSEL, sent|wparam|lparam|optional, 0, INT_MAX }, { EM_SETSEL, sent|wparam|lparam|optional, 0, INT_MAX }, { EM_SETSEL, sent|wparam|lparam|optional, 0, INT_MAX }, { HCBT_ACTIVATE, hook }, { WM_QUERYNEWPALETTE, sent|parent|optional }, /* TODO: this message should not be sent */ { WM_WINDOWPOSCHANGING, sent|parent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, { WM_WINDOWPOSCHANGING, sent|parent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, { WM_ACTIVATEAPP, sent|parent|wparam, 1 }, { WM_NCACTIVATE, sent|parent }, { WM_ACTIVATE, sent|parent|wparam, 1 }, { HCBT_SETFOCUS, hook }, { WM_SETFOCUS, sent|parent }, { WM_KILLFOCUS, sent|parent }, { WM_SETFOCUS, sent }, { WM_COMMAND, sent|parent|wparam, MAKELONG(200, EN_SETFOCUS) }, { WM_GETDLGCODE, sent|wparam|lparam, 0, 0 }, { WM_USER, sent|parent }, { WM_CHANGEUISTATE, sent|parent|optional }, { WM_UPDATEUISTATE, sent|parent|optional }, { WM_UPDATEUISTATE, sent|optional }, { 0 }};
static void test_dialog_messages(void){ WNDCLASSA cls; HWND hdlg, hedit1, hedit2, hfocus, parent, child, child2; LRESULT ret;
#define set_selection(hctl, start, end) \ ret = SendMessageA(hctl, EM_SETSEL, start, end); \ ok(ret == 1, "EM_SETSEL returned %ld\n", ret);
#define check_selection(hctl, start, end) \ ret = SendMessageA(hctl, EM_GETSEL, 0, 0); \ ok(ret == MAKELRESULT(start, end), "wrong selection (%d - %d)\n", LOWORD(ret), HIWORD(ret));
subclass_edit();
hdlg = CreateWindowExA(WS_EX_DLGMODALFRAME, "TestDialogClass", NULL, WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_DLGFRAME, 0, 0, 100, 100, 0, 0, 0, NULL); ok(hdlg != 0, "Failed to create custom dialog window\n");
hedit1 = CreateWindowExA(0, "my_edit_class", NULL, WS_CHILD|WS_BORDER|WS_VISIBLE|WS_TABSTOP, 0, 0, 80, 20, hdlg, (HMENU)1, 0, NULL); ok(hedit1 != 0, "Failed to create edit control\n"); hedit2 = CreateWindowExA(0, "my_edit_class", NULL, WS_CHILD|WS_BORDER|WS_VISIBLE|WS_TABSTOP, 0, 40, 80, 20, hdlg, (HMENU)2, 0, NULL); ok(hedit2 != 0, "Failed to create edit control\n");
SendMessageA(hedit1, WM_SETTEXT, 0, (LPARAM)"hello"); SendMessageA(hedit2, WM_SETTEXT, 0, (LPARAM)"bye");
hfocus = GetFocus(); ok(hfocus == hdlg, "wrong focus %p\n", hfocus);
SetFocus(hedit2); hfocus = GetFocus(); ok(hfocus == hedit2, "wrong focus %p\n", hfocus);
check_selection(hedit1, 0, 0); check_selection(hedit2, 0, 0);
set_selection(hedit2, 0, -1); check_selection(hedit2, 0, 3);
SetFocus(0); hfocus = GetFocus(); ok(hfocus == 0, "wrong focus %p\n", hfocus);
flush_sequence(); ret = DefDlgProcA(hdlg, WM_SETFOCUS, 0, 0); ok(ret == 0, "WM_SETFOCUS returned %ld\n", ret); ok_sequence(WmDefDlgSetFocus_1, "DefDlgProc(WM_SETFOCUS) 1", FALSE);
hfocus = GetFocus(); ok(hfocus == hedit1, "wrong focus %p\n", hfocus);
check_selection(hedit1, 0, 5); check_selection(hedit2, 0, 3);
flush_sequence(); ret = DefDlgProcA(hdlg, WM_SETFOCUS, 0, 0); ok(ret == 0, "WM_SETFOCUS returned %ld\n", ret); ok_sequence(WmDefDlgSetFocus_2, "DefDlgProc(WM_SETFOCUS) 2", FALSE);
hfocus = GetFocus(); ok(hfocus == hedit1, "wrong focus %p\n", hfocus);
check_selection(hedit1, 0, 5); check_selection(hedit2, 0, 3);
EndDialog(hdlg, 0); DestroyWindow(hedit1); DestroyWindow(hedit2); DestroyWindow(hdlg); flush_sequence();
#undef set_selection#undef check_selection
ok(GetClassInfoA(0, "#32770", &cls), "GetClassInfo failed\n"); cls.lpszClassName = "MyDialogClass"; cls.hInstance = GetModuleHandleA(NULL); /* need a cast since a dlgproc is used as a wndproc */ cls.lpfnWndProc = test_dlg_proc; if (!RegisterClassA(&cls)) assert(0);
SetFocus(0); flush_sequence(); hdlg = CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", 0, test_dlg_proc, 0); ok(IsWindow(hdlg), "CreateDialogParam failed\n"); ok_sequence(WmCreateDialogParamSeq_0, "CreateDialogParam_0", FALSE); hfocus = GetFocus(); ok(hfocus == 0, "wrong focus %p\n", hfocus); EndDialog(hdlg, 0); DestroyWindow(hdlg); flush_sequence();
SetFocus(0); flush_sequence(); hdlg = CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", 0, test_dlg_proc, 1); ok(IsWindow(hdlg), "CreateDialogParam failed\n"); ok_sequence(WmCreateDialogParamSeq_1, "CreateDialogParam_1", FALSE); hfocus = GetFocus(); ok(hfocus == hdlg, "wrong focus %p\n", hfocus); EndDialog(hdlg, 0); DestroyWindow(hdlg); flush_sequence();
hdlg = CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", 0, NULL, 0); ok(IsWindow(hdlg), "CreateDialogParam failed\n"); ok_sequence(WmCreateDialogParamSeq_2, "CreateDialogParam_2", FALSE); EndDialog(hdlg, 0); DestroyWindow(hdlg); flush_sequence();
hdlg = CreateDialogParamA(0, "FOCUS_TEST_DIALOG_3", 0, test_dlg_proc2, 0); ok(IsWindow(hdlg), "CreateDialogParam failed\n"); ok_sequence(WmCreateDialogParamSeq_3, "CreateDialogParam_3", TRUE); EndDialog(hdlg, 0); DestroyWindow(hdlg); flush_sequence();
UnregisterClassA( cls.lpszClassName, cls.hInstance ); cls.lpfnWndProc = test_dlg_proc4; ok( RegisterClassA(&cls), "failed to register class again\n" ); hdlg = CreateDialogParamA(0, "FOCUS_TEST_DIALOG_4", 0, test_dlg_proc3, 0); ok(IsWindow(hdlg), "CreateDialogParam failed\n"); ok_sequence(WmCreateDialogParamSeq_4, "CreateDialogParam_4", TRUE); EndDialog(hdlg, 0); DestroyWindow(hdlg); flush_sequence();
UnregisterClassA(cls.lpszClassName, cls.hInstance);
parent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 200, 200, 0, 0, 0, NULL); ok (parent != 0, "Failed to create parent window\n");
/* This child has no parent set. We will later call SetParent on it, * so that it will have a parent set, but no WS_CHILD style. */ child = CreateWindowExA(0, "TestWindowClass", "Test child", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 200, 200, 0, 0, 0, NULL); ok (child != 0, "Failed to create child window\n");
/* This is a regular child window. When used as an owner, the other * child window will be used. */ child2 = CreateWindowExA(0, "SimpleWindowClass", "Test child2", WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CHILD, 100, 100, 200, 200, child, 0, 0, NULL); ok (child2 != 0, "Failed to create child window\n");
SetParent(child, parent); SetFocus(child);
flush_sequence(); DialogBoxA( 0, "TEST_DIALOG", child2, TestModalDlgProc2 ); ok_sequence(WmModalDialogSeq_2, "ModalDialog2", TRUE);
DestroyWindow(child2); DestroyWindow(child); DestroyWindow(parent); flush_sequence();}
static void test_enddialog_seq(HWND dialog, HWND owner){ const struct message seq[] = { { WM_ENABLE, sent }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { HCBT_ACTIVATE, hook|wparam, (WPARAM)owner }, { WM_NCACTIVATE, sent|wparam|lparam, WA_INACTIVE, (LPARAM)owner }, { WM_ACTIVATE, sent|wparam|lparam, WA_INACTIVE, (LPARAM)owner }, /* FIXME: Following two are optional because Wine sends WM_QUERYNEWPALETTE instead of WM_WINDOWPOSCHANGING */ { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, { WM_QUERYNEWPALETTE, sent|optional }, { WM_NCACTIVATE, sent|wparam|lparam, WA_ACTIVE, (LPARAM)dialog }, { WM_GETTEXT, sent|optional|defwinproc }, { WM_ACTIVATE, sent|wparam|lparam, WA_ACTIVE, (LPARAM)dialog }, { HCBT_SETFOCUS, hook|wparam, (WPARAM)owner }, { WM_KILLFOCUS, sent|wparam, (WPARAM)owner }, { WM_SETFOCUS, sent|defwinproc|wparam, (WPARAM)dialog }, { 0 } };
flush_sequence(); EndDialog(dialog, 0); ok_sequence(seq, "EndDialog", FALSE);}
static void test_enddialog_seq2(HWND dialog, HWND owner){ const struct message seq[] = { { WM_ENABLE, parent|sent }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { HCBT_ACTIVATE, hook|wparam, (WPARAM)owner }, { WM_NCACTIVATE, sent|wparam|lparam, WA_INACTIVE, (LPARAM)owner }, { WM_ACTIVATE, sent|wparam|lparam, WA_INACTIVE, (LPARAM)owner }, { WM_WINDOWPOSCHANGING, sent|optional|wparam, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_WINDOWPOSCHANGING, sent|optional|wparam, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { HCBT_SETFOCUS, hook|wparam, (WPARAM)owner }, { WM_KILLFOCUS, sent|wparam, (WPARAM)owner }, { WM_SETFOCUS, sent|parent|defwinproc|wparam, (WPARAM)dialog }, { 0 } };
flush_sequence(); EndDialog(dialog, 0); ok_sequence(seq, "EndDialog2", FALSE);}
static void test_EndDialog(void){ HWND hparent, hother, hactive, hdlg, hchild; WNDCLASSA cls;
hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_DISABLED, 100, 100, 200, 200, 0, 0, 0, NULL); ok (hparent != 0, "Failed to create parent window\n");
hother = CreateWindowExA(0, "TestParentClass", "Test parent 2", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 200, 100, 200, 200, 0, 0, 0, NULL); ok (hother != 0, "Failed to create parent window\n");
ok(GetClassInfoA(0, "#32770", &cls), "GetClassInfo failed\n"); cls.lpszClassName = "MyDialogClass"; cls.hInstance = GetModuleHandleA(NULL); cls.lpfnWndProc = test_dlg_proc; if (!RegisterClassA(&cls)) assert(0);
flush_sequence(); SetForegroundWindow(hother); hactive = GetForegroundWindow(); ok(hother == hactive, "Wrong window has focus (%p != %p)\n", hother, hactive);
/* create a dialog where the parent is disabled, this parent should be * enabled and receive focus when dialog exits */ hdlg = CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", hparent, test_dlg_proc, 0); ok(IsWindow(hdlg), "CreateDialogParam failed\n"); SetForegroundWindow(hdlg); hactive = GetForegroundWindow(); ok(hdlg == hactive, "Wrong window has focus (%p != %p)\n", hdlg, hactive); EndDialog(hdlg, 0); ok(IsWindowEnabled(hparent), "parent is not enabled\n"); hactive = GetForegroundWindow(); ok(hparent == hactive, "Wrong window has focus (parent != active) (active: %p, parent: %p, dlg: %p, other: %p)\n", hactive, hparent, hdlg, hother); DestroyWindow(hdlg); flush_sequence();
/* create a dialog where the parent is disabled and set active window to other window before calling EndDialog */ EnableWindow(hparent, FALSE); hdlg = CreateWindowExA(0, "TestDialogClass", NULL, WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_DLGFRAME, 0, 0, 100, 100, hparent, 0, 0, NULL); ok(IsWindow(hdlg), "CreateDialogParam failed\n"); flush_sequence(); SetForegroundWindow(hother); flush_sequence(); hactive = GetForegroundWindow(); ok(hactive == hother, "Wrong foreground (%p != %p)\n", hactive, hother); hactive = GetActiveWindow(); ok(hactive == hother, "Wrong active window (%p != %p)\n", hactive, hother); EndDialog(hdlg, 0); ok(IsWindowEnabled(hparent), "parent is not enabled\n"); hactive = GetForegroundWindow(); ok(hother == hactive, "Wrong window has focus (other != active) (active: %p, parent: %p, dlg: %p, other: %p)\n", hactive, hparent, hdlg, hother); DestroyWindow(hdlg); flush_sequence();
DestroyWindow( hparent );
hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_POPUP | WS_VISIBLE | WS_DISABLED, 100, 100, 200, 200, 0, 0, 0, NULL); ok (hparent != 0, "Failed to create parent window\n");
hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_DISABLED, 0, 0, 0, 0, 0, 0, 0, NULL); ok (hchild != 0, "Failed to create child window\n");
SetParent(hchild, hparent);
flush_sequence(); SetForegroundWindow(hother); hactive = GetForegroundWindow(); ok(hother == hactive, "Wrong foreground window (%p != %p)\n", hother, hactive);
hdlg = CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", hchild, test_dlg_proc, 0); ok(IsWindow(hdlg), "CreateDialogParam failed\n");
SetForegroundWindow(hdlg); test_enddialog_seq(hdlg, hchild);
hactive = GetForegroundWindow(); ok(hactive == hchild, "Wrong foreground window (active: %p, parent: %p, dlg: %p, other: %p child: %p)\n", hactive, hparent, hdlg, hother, hchild);
DestroyWindow(hdlg);
/* Now set WS_CHILD style flag so that it's a real child and its parent will be dialog's owner. */ SetWindowLongW(hchild, GWL_STYLE, GetWindowLongW(hchild, GWL_STYLE) | WS_CHILD);
SetForegroundWindow(hother); hactive = GetForegroundWindow(); ok(hother == hactive, "Wrong foreground window (%p != %p)\n", hother, hactive);
hdlg = CreateDialogParamA(0, "CLASS_TEST_DIALOG_2", hchild, test_dlg_proc, 0); ok(IsWindow(hdlg), "CreateDialogParam failed\n");
SetForegroundWindow(hdlg); test_enddialog_seq2(hdlg, hparent);
hactive = GetForegroundWindow(); ok(hactive == hparent, "Wrong foreground window (active: %p, parent: %p, dlg: %p, other: %p child: %p)\n", hactive, hparent, hdlg, hother, hchild); DestroyWindow(hdlg); DestroyWindow(hchild); DestroyWindow(hparent); DestroyWindow(hother); flush_sequence();
UnregisterClassA(cls.lpszClassName, cls.hInstance);}
static void test_nullCallback(void){ HWND hwnd;
hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW, 100, 100, 200, 200, 0, 0, 0, NULL); ok (hwnd != 0, "Failed to create overlapped window\n");
SendMessageCallbackA(hwnd,WM_NULL,0,0,NULL,0); flush_events(); DestroyWindow(hwnd);}
/* SetActiveWindow( 0 ) hwnd visible */static const struct message SetActiveWindowSeq0[] ={ { HCBT_ACTIVATE, hook|optional }, { WM_NCACTIVATE, sent|wparam, 0 }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ACTIVATE, sent|wparam, 0 }, { WM_ACTIVATEAPP, sent|wparam|optional, 0 }, { WM_ACTIVATEAPP, sent|wparam|optional, 0 }, { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, { WM_KILLFOCUS, sent|optional }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, { WM_NCACTIVATE, sent|wparam|optional, 1 }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ACTIVATE, sent|wparam|optional, 1 }, { HCBT_SETFOCUS, hook|optional }, { WM_KILLFOCUS, sent|defwinproc|optional }, { WM_IME_SETCONTEXT, sent|defwinproc|optional }, { WM_IME_SETCONTEXT, sent|defwinproc|optional }, { WM_IME_SETCONTEXT, sent|optional }, { WM_IME_SETCONTEXT, sent|optional }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { WM_SETFOCUS, sent|defwinproc|optional }, { WM_GETTEXT, sent|optional }, { 0 }};/* SetActiveWindow( hwnd ) hwnd visible */static const struct message SetActiveWindowSeq1[] ={ { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, { 0 }};/* SetActiveWindow( popup ) hwnd visible, popup visible */static const struct message SetActiveWindowSeq2[] ={ { HCBT_ACTIVATE, hook }, { WM_NCACTIVATE, sent|wparam, 0 }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ACTIVATE, sent|wparam, 0 }, { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, { WM_NCPAINT, sent|optional }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { WM_NCACTIVATE, sent|wparam, 1 }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ACTIVATE, sent|wparam, 1 }, { HCBT_SETFOCUS, hook }, { WM_KILLFOCUS, sent|defwinproc }, { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 }, { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { WM_SETFOCUS, sent|defwinproc }, { WM_GETTEXT, sent|optional }, { 0 }};
/* SetActiveWindow( hwnd ) hwnd not visible */static const struct message SetActiveWindowSeq3[] ={ { HCBT_ACTIVATE, hook }, { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE }, { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOACTIVATE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { WM_ACTIVATEAPP, sent|wparam, 1 }, { WM_ACTIVATEAPP, sent|wparam, 1 }, { WM_NCACTIVATE, sent|wparam, 1 }, { WM_ACTIVATE, sent|wparam, 1 }, { HCBT_SETFOCUS, hook }, { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { WM_SETFOCUS, sent|defwinproc }, { 0 }};/* SetActiveWindow( popup ) hwnd not visible, popup not visible */static const struct message SetActiveWindowSeq4[] ={ { HCBT_ACTIVATE, hook }, { WM_NCACTIVATE, sent|wparam, 0 }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ACTIVATE, sent|wparam, 0 }, { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { WM_NCACTIVATE, sent|wparam, 1 }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ACTIVATE, sent|wparam, 1 }, { HCBT_SETFOCUS, hook }, { WM_KILLFOCUS, sent|defwinproc }, { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 }, { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { WM_SETFOCUS, sent|defwinproc }, { 0 }};
static void test_SetActiveWindow(void){ HWND hwnd, popup, ret;
hwnd = CreateWindowExA(0, "TestWindowClass", "Test SetActiveWindow", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 200, 200, 0, 0, 0, NULL);
popup = CreateWindowExA(0, "TestWindowClass", "Test SetActiveWindow", WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_POPUP, 100, 100, 200, 200, hwnd, 0, 0, NULL);
ok(hwnd != 0, "Failed to create overlapped window\n"); ok(popup != 0, "Failed to create popup window\n"); SetForegroundWindow( popup ); flush_sequence();
trace("SetActiveWindow(0)\n"); ret = SetActiveWindow(0); ok( ret == popup, "Failed to SetActiveWindow(0)\n"); ok_sequence(SetActiveWindowSeq0, "SetActiveWindow(0)", FALSE); flush_sequence();
trace("SetActiveWindow(hwnd), hwnd visible\n"); ret = SetActiveWindow(hwnd); if (ret == hwnd) ok_sequence(SetActiveWindowSeq1, "SetActiveWindow(hwnd), hwnd visible", TRUE); flush_sequence();
trace("SetActiveWindow(popup), hwnd visible, popup visible\n"); ret = SetActiveWindow(popup); ok( ret == hwnd, "Failed to SetActiveWindow(popup), popup visible\n"); ok_sequence(SetActiveWindowSeq2, "SetActiveWindow(popup), hwnd visible, popup visible", FALSE); flush_sequence();
ShowWindow(hwnd, SW_HIDE); ShowWindow(popup, SW_HIDE); flush_sequence();
trace("SetActiveWindow(hwnd), hwnd not visible\n"); ret = SetActiveWindow(hwnd); ok( ret == NULL, "SetActiveWindow(hwnd), hwnd not visible, previous is %p\n", ret ); ok_sequence(SetActiveWindowSeq3, "SetActiveWindow(hwnd), hwnd not visible", TRUE); flush_sequence();
trace("SetActiveWindow(popup), hwnd not visible, popup not visible\n"); ret = SetActiveWindow(popup); ok( ret == hwnd, "Failed to SetActiveWindow(popup)\n"); ok_sequence(SetActiveWindowSeq4, "SetActiveWindow(popup), hwnd not visible, popup not visible", TRUE); flush_sequence();
trace("done\n");
DestroyWindow(hwnd);}
static const struct message SetForegroundWindowSeq[] ={ { WM_NCACTIVATE, sent|wparam, 0 }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ACTIVATE, sent|wparam, 0 }, { WM_ACTIVATEAPP, sent|wparam, 0 }, { WM_KILLFOCUS, sent }, { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, { WM_IME_NOTIFY, sent|wparam|optional|defwinproc, 1 }, { 0 }};
static void test_SetForegroundWindow(void){ HWND hwnd;
hwnd = CreateWindowExA(0, "TestWindowClass", "Test SetForegroundWindow", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 200, 200, 0, 0, 0, NULL); ok (hwnd != 0, "Failed to create overlapped window\n"); SetForegroundWindow( hwnd ); flush_sequence();
trace("SetForegroundWindow( 0 )\n"); SetForegroundWindow( 0 ); ok_sequence(WmEmptySeq, "SetForegroundWindow( 0 ) away from foreground top level window", FALSE); trace("SetForegroundWindow( GetDesktopWindow() )\n"); SetForegroundWindow( GetDesktopWindow() ); ok_sequence(SetForegroundWindowSeq, "SetForegroundWindow( desktop ) away from " "foreground top level window", FALSE); trace("done\n");
DestroyWindow(hwnd);}
static DWORD get_input_codepage( void ){ DWORD cp; int ret; HKL hkl = GetKeyboardLayout( 0 );
ret = GetLocaleInfoW( LOWORD(hkl), LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER, (WCHAR *)&cp, sizeof(cp) / sizeof(WCHAR) ); if (!ret) cp = CP_ACP; return cp;}
static void test_dbcs_wm_char(void){ BYTE dbch[2]; WCHAR wch, bad_wch; HWND hwnd, hwnd2; MSG msg; DWORD time; POINT pt; DWORD_PTR res; CPINFOEXA cpinfo; UINT i, j, k; struct message wmCharSeq[2]; BOOL ret; DWORD cp = get_input_codepage();
if (!pGetCPInfoExA) { win_skip("GetCPInfoExA is not available\n"); return; }
pGetCPInfoExA( cp, 0, &cpinfo ); if (cpinfo.MaxCharSize != 2) { skip( "Skipping DBCS WM_CHAR test in SBCS codepage '%s'\n", cpinfo.CodePageName ); return; }
dbch[0] = dbch[1] = 0; wch = 0; bad_wch = cpinfo.UnicodeDefaultChar; for (i = 0; !wch && i < MAX_LEADBYTES && cpinfo.LeadByte[i]; i += 2) for (j = cpinfo.LeadByte[i]; !wch && j <= cpinfo.LeadByte[i+1]; j++) for (k = 128; k <= 255; k++) { char str[2]; WCHAR wstr[2]; str[0] = j; str[1] = k; if (MultiByteToWideChar( cp, 0, str, 2, wstr, 2 ) == 1 && WideCharToMultiByte( cp, 0, wstr, 1, str, 2, NULL, NULL ) == 2 && (BYTE)str[0] == j && (BYTE)str[1] == k && HIBYTE(wstr[0]) && HIBYTE(wstr[0]) != 0xff) { dbch[0] = j; dbch[1] = k; wch = wstr[0]; break; } }
if (!wch) { skip( "Skipping DBCS WM_CHAR test, no appropriate char found\n" ); return; } trace( "using dbcs char %02x,%02x wchar %04x bad wchar %04x codepage '%s'\n", dbch[0], dbch[1], wch, bad_wch, cpinfo.CodePageName );
hwnd = CreateWindowExW(0, testWindowClassW, NULL, WS_OVERLAPPEDWINDOW, 100, 100, 200, 200, 0, 0, 0, NULL); hwnd2 = CreateWindowExW(0, testWindowClassW, NULL, WS_OVERLAPPEDWINDOW, 100, 100, 200, 200, 0, 0, 0, NULL); ok (hwnd != 0, "Failed to create overlapped window\n"); ok (hwnd2 != 0, "Failed to create overlapped window\n"); flush_sequence();
memset( wmCharSeq, 0, sizeof(wmCharSeq) ); wmCharSeq[0].message = WM_CHAR; wmCharSeq[0].flags = sent|wparam; wmCharSeq[0].wParam = wch;
/* posted message */ PostMessageA( hwnd, WM_CHAR, dbch[0], 0 ); ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); ok( !ret, "got message %x\n", msg.message ); PostMessageA( hwnd, WM_CHAR, dbch[1], 0 ); ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); ok( ret, "no message\n" ); ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); ok( msg.wParam == wch, "bad wparam %lx/%x\n", msg.wParam, wch ); ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); ok( !ret, "got message %x\n", msg.message );
/* posted thread message */ PostThreadMessageA( GetCurrentThreadId(), WM_CHAR, dbch[0], 0 ); ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); ok( !ret, "got message %x\n", msg.message ); PostMessageA( hwnd, WM_CHAR, dbch[1], 0 ); ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); ok( ret, "no message\n" ); ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); ok( msg.wParam == wch, "bad wparam %lx/%x\n", msg.wParam, wch ); ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); ok( !ret, "got message %x\n", msg.message );
/* sent message */ flush_sequence(); SendMessageA( hwnd, WM_CHAR, dbch[0], 0 ); ok_sequence( WmEmptySeq, "no messages", FALSE ); SendMessageA( hwnd, WM_CHAR, dbch[1], 0 ); ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); ok( !ret, "got message %x\n", msg.message );
/* sent message with timeout */ flush_sequence(); SendMessageTimeoutA( hwnd, WM_CHAR, dbch[0], 0, SMTO_NORMAL, 0, &res ); ok_sequence( WmEmptySeq, "no messages", FALSE ); SendMessageTimeoutA( hwnd, WM_CHAR, dbch[1], 0, SMTO_NORMAL, 0, &res ); ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); ok( !ret, "got message %x\n", msg.message );
/* sent message with timeout and callback */ flush_sequence(); SendMessageTimeoutA( hwnd, WM_CHAR, dbch[0], 0, SMTO_NORMAL, 0, &res ); ok_sequence( WmEmptySeq, "no messages", FALSE ); SendMessageCallbackA( hwnd, WM_CHAR, dbch[1], 0, NULL, 0 ); ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); ok( !ret, "got message %x\n", msg.message );
/* sent message with callback */ flush_sequence(); SendNotifyMessageA( hwnd, WM_CHAR, dbch[0], 0 ); ok_sequence( WmEmptySeq, "no messages", FALSE ); SendMessageCallbackA( hwnd, WM_CHAR, dbch[1], 0, NULL, 0 ); ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); ok( !ret, "got message %x\n", msg.message );
/* direct window proc call */ flush_sequence(); CallWindowProcA( (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ), hwnd, WM_CHAR, dbch[0], 0 ); ok_sequence( WmEmptySeq, "no messages", FALSE ); CallWindowProcA( (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ), hwnd, WM_CHAR, dbch[1], 0 ); ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE );
/* dispatch message */ msg.hwnd = hwnd; msg.message = WM_CHAR; msg.wParam = dbch[0]; msg.lParam = 0; DispatchMessageA( &msg ); ok_sequence( WmEmptySeq, "no messages", FALSE ); msg.wParam = dbch[1]; DispatchMessageA( &msg ); ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE );
/* window handle is irrelevant */ flush_sequence(); SendMessageA( hwnd2, WM_CHAR, dbch[0], 0 ); ok_sequence( WmEmptySeq, "no messages", FALSE ); SendMessageA( hwnd, WM_CHAR, dbch[1], 0 ); ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); ok( !ret, "got message %x\n", msg.message );
/* interleaved post and send */ flush_sequence(); PostMessageA( hwnd2, WM_CHAR, dbch[0], 0 ); SendMessageA( hwnd2, WM_CHAR, dbch[0], 0 ); ok_sequence( WmEmptySeq, "no messages", FALSE ); ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); ok( !ret, "got message %x\n", msg.message ); PostMessageA( hwnd, WM_CHAR, dbch[1], 0 ); ok_sequence( WmEmptySeq, "no messages", FALSE ); ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); ok( ret, "no message\n" ); ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); ok( msg.wParam == wch, "bad wparam %lx/%x\n", msg.wParam, wch ); ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); ok( !ret, "got message %x\n", msg.message ); SendMessageA( hwnd, WM_CHAR, dbch[1], 0 ); ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); ok( !ret, "got message %x\n", msg.message );
/* interleaved sent message and winproc */ flush_sequence(); SendMessageA( hwnd, WM_CHAR, dbch[0], 0 ); CallWindowProcA( (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ), hwnd, WM_CHAR, dbch[0], 0 ); ok_sequence( WmEmptySeq, "no messages", FALSE ); SendMessageA( hwnd, WM_CHAR, dbch[1], 0 ); ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); CallWindowProcA( (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ), hwnd, WM_CHAR, dbch[1], 0 ); ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE );
/* interleaved winproc and dispatch */ msg.hwnd = hwnd; msg.message = WM_CHAR; msg.wParam = dbch[0]; msg.lParam = 0; CallWindowProcA( (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ), hwnd, WM_CHAR, dbch[0], 0 ); DispatchMessageA( &msg ); ok_sequence( WmEmptySeq, "no messages", FALSE ); msg.wParam = dbch[1]; DispatchMessageA( &msg ); ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); CallWindowProcA( (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ), hwnd, WM_CHAR, dbch[1], 0 ); ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE );
/* interleaved sends */ flush_sequence(); SendMessageA( hwnd, WM_CHAR, dbch[0], 0 ); SendMessageCallbackA( hwnd, WM_CHAR, dbch[0], 0, NULL, 0 ); ok_sequence( WmEmptySeq, "no messages", FALSE ); SendMessageTimeoutA( hwnd, WM_CHAR, dbch[1], 0, SMTO_NORMAL, 0, &res ); ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); SendMessageA( hwnd, WM_CHAR, dbch[1], 0 ); ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE );
/* dbcs WM_CHAR */ flush_sequence(); SendMessageA( hwnd2, WM_CHAR, (dbch[1] << 8) | dbch[0], 0 ); ok_sequence( wmCharSeq, "Unicode WM_CHAR", FALSE ); ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); ok( !ret, "got message %x\n", msg.message );
/* other char messages are not magic */ PostMessageA( hwnd, WM_SYSCHAR, dbch[0], 0 ); ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); ok( ret, "no message\n" ); ok( msg.message == WM_SYSCHAR, "unexpected message %x\n", msg.message ); ok( msg.wParam == bad_wch, "bad wparam %lx/%x\n", msg.wParam, bad_wch ); ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); ok( !ret, "got message %x\n", msg.message ); PostMessageA( hwnd, WM_DEADCHAR, dbch[0], 0 ); ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); ok( ret, "no message\n" ); ok( msg.message == WM_DEADCHAR, "unexpected message %x\n", msg.message ); ok( msg.wParam == bad_wch, "bad wparam %lx/%x\n", msg.wParam, bad_wch ); ret = PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ); ok( !ret, "got message %x\n", msg.message );
/* test retrieving messages */
PostMessageW( hwnd, WM_CHAR, wch, 0 ); ret = PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ); ok( ret, "no message\n" ); ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); ok( msg.wParam == dbch[0], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); ret = PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ); ok( ret, "no message\n" ); ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); ok( msg.wParam == dbch[1], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); ret = PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ); ok( !ret, "got message %x\n", msg.message );
/* message filters */ PostMessageW( hwnd, WM_CHAR, wch, 0 ); ret = PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ); ok( ret, "no message\n" ); ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); ok( msg.wParam == dbch[0], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); /* message id is filtered, hwnd is not */ ret = PeekMessageA( &msg, hwnd, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ); ok( !ret, "no message\n" ); ret = PeekMessageA( &msg, hwnd2, 0, 0, PM_REMOVE ); ok( ret, "no message\n" ); ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); ok( msg.wParam == dbch[1], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); ret = PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ); ok( !ret, "got message %x\n", msg.message );
/* mixing GetMessage and PostMessage */ PostMessageW( hwnd, WM_CHAR, wch, 0xbeef ); ok( GetMessageA( &msg, hwnd, 0, 0 ), "no message\n" ); ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); ok( msg.wParam == dbch[0], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); ok( msg.lParam == 0xbeef, "bad lparam %lx\n", msg.lParam ); time = msg.time; pt = msg.pt; ok( time - GetTickCount() <= 100, "bad time %x\n", msg.time ); ret = PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ); ok( ret, "no message\n" ); ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); ok( msg.wParam == dbch[1], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); ok( msg.lParam == 0xbeef, "bad lparam %lx\n", msg.lParam ); ok( msg.time == time, "bad time %x/%x\n", msg.time, time ); ok( msg.pt.x == pt.x && msg.pt.y == pt.y, "bad point %u,%u/%u,%u\n", msg.pt.x, msg.pt.y, pt.x, pt.y ); ret = PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ); ok( !ret, "got message %x\n", msg.message );
/* without PM_REMOVE */ PostMessageW( hwnd, WM_CHAR, wch, 0 ); ret = PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ); ok( ret, "no message\n" ); ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); ok( msg.wParam == dbch[0], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); ret = PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ); ok( ret, "no message\n" ); ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); ok( msg.wParam == dbch[0], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); ret = PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ); ok( ret, "no message\n" ); ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); ok( msg.wParam == dbch[1], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); ret = PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ); ok( ret, "no message\n" ); ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); ok( msg.wParam == dbch[1], "bad wparam %lx/%x\n", msg.wParam, dbch[0] ); ret = PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ); ok( !ret, "got message %x\n", msg.message );
DestroyWindow(hwnd); DestroyWindow(hwnd2);}
static void test_unicode_wm_char(void){ HWND hwnd; MSG msg; struct message seq[2]; HKL hkl_orig, hkl_greek; DWORD cp; LCID thread_locale;
hkl_orig = GetKeyboardLayout( 0 ); GetLocaleInfoW( LOWORD( hkl_orig ), LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER, (WCHAR*)&cp, sizeof(cp) / sizeof(WCHAR) ); if (cp != 1252) { skip( "Default codepage %d\n", cp ); return; }
hkl_greek = LoadKeyboardLayoutA( "00000408", 0 ); if (!hkl_greek || hkl_greek == hkl_orig /* win2k */) { skip( "Unable to load Greek keyboard layout\n" ); return; }
hwnd = CreateWindowExW( 0, testWindowClassW, NULL, WS_OVERLAPPEDWINDOW, 100, 100, 200, 200, 0, 0, 0, NULL ); flush_sequence();
PostMessageW( hwnd, WM_CHAR, 0x3b1, 0 );
while (GetMessageW( &msg, hwnd, 0, 0 )) { if (!ignore_message( msg.message )) break; }
ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); ok( msg.wParam == 0x3b1, "bad wparam %lx\n", msg.wParam ); ok( msg.lParam == 0, "bad lparam %lx\n", msg.lParam );
DispatchMessageW( &msg );
memset( seq, 0, sizeof(seq) ); seq[0].message = WM_CHAR; seq[0].flags = sent|wparam; seq[0].wParam = 0x3b1;
ok_sequence( seq, "unicode WM_CHAR", FALSE );
flush_sequence();
/* greek alpha -> 'a' in cp1252 */ PostMessageW( hwnd, WM_CHAR, 0x3b1, 0 );
ok( GetMessageA( &msg, hwnd, 0, 0 ), "no message\n" ); ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); ok( msg.wParam == 0x61, "bad wparam %lx\n", msg.wParam ); ok( msg.lParam == 0, "bad lparam %lx\n", msg.lParam );
DispatchMessageA( &msg );
seq[0].wParam = 0x61; ok_sequence( seq, "unicode WM_CHAR", FALSE );
thread_locale = GetThreadLocale(); ActivateKeyboardLayout( hkl_greek, 0 ); ok( GetThreadLocale() == thread_locale, "locale changed from %08x to %08x\n", thread_locale, GetThreadLocale() );
flush_sequence();
/* greek alpha -> 0xe1 in cp1253 */ PostMessageW( hwnd, WM_CHAR, 0x3b1, 0 );
ok( GetMessageA( &msg, hwnd, 0, 0 ), "no message\n" ); ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd ); ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message ); ok( msg.wParam == 0xe1, "bad wparam %lx\n", msg.wParam ); ok( msg.lParam == 0, "bad lparam %lx\n", msg.lParam );
DispatchMessageA( &msg );
seq[0].wParam = 0x3b1; ok_sequence( seq, "unicode WM_CHAR", FALSE );
DestroyWindow( hwnd ); ActivateKeyboardLayout( hkl_orig, 0 ); UnloadKeyboardLayout( hkl_greek );}
#define ID_LISTBOX 0x000f
static const struct message wm_lb_setcursel_0[] ={ { LB_SETCURSEL, sent|wparam|lparam, 0, 0 }, { WM_CTLCOLORLISTBOX, sent|parent }, { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x000120f2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 1 }, { EVENT_OBJECT_SELECTION, winevent_hook|wparam|lparam, OBJID_CLIENT, 1 }, { 0 }};static const struct message wm_lb_setcursel_1[] ={ { LB_SETCURSEL, sent|wparam|lparam, 1, 0 }, { WM_CTLCOLORLISTBOX, sent|parent }, { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x000020f2 }, { WM_CTLCOLORLISTBOX, sent|parent }, { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x000121f2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 2 }, { EVENT_OBJECT_SELECTION, winevent_hook|wparam|lparam, OBJID_CLIENT, 2 }, { 0 }};static const struct message wm_lb_setcursel_2[] ={ { LB_SETCURSEL, sent|wparam|lparam, 2, 0 }, { WM_CTLCOLORLISTBOX, sent|parent }, { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x000021f2 }, { WM_CTLCOLORLISTBOX, sent|parent }, { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x000122f2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 3 }, { EVENT_OBJECT_SELECTION, winevent_hook|wparam|lparam, OBJID_CLIENT, 3 }, { 0 }};static const struct message wm_lb_click_0[] ={ { WM_LBUTTONDOWN, sent|wparam|lparam, 0, MAKELPARAM(1,1) }, { HCBT_SETFOCUS, hook }, { WM_KILLFOCUS, sent|parent }, { WM_IME_SETCONTEXT, sent|wparam|optional|parent, 0 }, { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|defwinproc },
{ WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x001142f2 }, { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_LISTBOX, LBN_SETFOCUS) }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 3 }, { WM_LBTRACKPOINT, sent|wparam|lparam|parent, 0, MAKELPARAM(1,1) }, { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
{ WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x000142f2 }, { WM_CTLCOLORLISTBOX, sent|parent }, { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x000022f2 }, { WM_CTLCOLORLISTBOX, sent|parent }, { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x000120f2 }, { WM_DRAWITEM, sent|wparam|lparam|parent, ID_LISTBOX, 0x001140f2 },
{ EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 1 }, { EVENT_OBJECT_SELECTION, winevent_hook|wparam|lparam, OBJID_CLIENT, 1 },
{ WM_LBUTTONUP, sent|wparam|lparam, 0, 0 }, { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 }, { WM_CAPTURECHANGED, sent|wparam|lparam|defwinproc, 0, 0 }, { WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_LISTBOX, LBN_SELCHANGE) }, { 0 }};static const struct message wm_lb_deletestring[] ={ { LB_DELETESTRING, sent|wparam|lparam, 0, 0 }, { WM_DELETEITEM, sent|wparam|parent|optional, ID_LISTBOX, 0 }, { WM_DRAWITEM, sent|wparam|parent|optional, ID_LISTBOX }, { WM_DRAWITEM, sent|wparam|parent|optional, ID_LISTBOX }, { 0 }};static const struct message wm_lb_deletestring_reset[] ={ { LB_DELETESTRING, sent|wparam|lparam, 0, 0 }, { LB_RESETCONTENT, sent|wparam|lparam|defwinproc|optional, 0, 0 }, { WM_DELETEITEM, sent|wparam|parent|optional, ID_LISTBOX, 0 }, { WM_DRAWITEM, sent|wparam|parent|optional, ID_LISTBOX }, { WM_DRAWITEM, sent|wparam|parent|optional, ID_LISTBOX }, { 0 }};static const struct message wm_lb_addstring[] ={ { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ef }, { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ed }, { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ee }, { 0 }};static const struct message wm_lb_addstring_ownerdraw[] ={ { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ed }, { WM_MEASUREITEM, sent|wparam|lparam|parent, 0xf0f2, 0xf30604ed }, { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ee }, { WM_MEASUREITEM, sent|wparam|lparam|parent, 0xf1f2, 0xf30604ee }, { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ef }, { WM_MEASUREITEM, sent|wparam|lparam|parent, 0xf2f2, 0xf30604ef }, { 0 }};static const struct message wm_lb_addstring_sort_ownerdraw[] ={ { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ed }, { WM_MEASUREITEM, sent|wparam|lparam|parent, 0xf0f2, 0xf30604ed }, { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ee }, { WM_COMPAREITEM, sent|wparam|lparam|parent, 0xf30604ed, 0xf30604ee }, { WM_MEASUREITEM, sent|wparam|lparam|parent, 0xf1f2, 0xf30604ee }, { LB_ADDSTRING, sent|wparam|lparam, 0, 0xf30604ef }, { WM_COMPAREITEM, sent|wparam|lparam|parent, 0xf30604ed, 0xf30604ef }, { WM_COMPAREITEM, sent|wparam|lparam|parent, 0xf30604ee, 0xf30604ef }, { WM_MEASUREITEM, sent|wparam|lparam|parent, 0xf2f2, 0xf30604ef }, { 0 }};
#define check_lb_state(a1, a2, a3, a4, a5) check_lb_state_dbg(a1, a2, a3, a4, a5, __LINE__)
static LRESULT (WINAPI *listbox_orig_proc)(HWND, UINT, WPARAM, LPARAM);
static LRESULT WINAPI listbox_hook_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp){ static LONG defwndproc_counter = 0; LRESULT ret; struct recvd_message msg;
/* do not log painting messages */ if (message != WM_PAINT && message != WM_NCPAINT && message != WM_SYNCPAINT && message != WM_ERASEBKGND && message != WM_NCHITTEST && message != WM_GETTEXT && !ignore_message( message )) { msg.hwnd = hwnd; msg.message = message; msg.flags = sent|wparam|lparam; if (defwndproc_counter) msg.flags |= defwinproc; msg.wParam = wp; if (message == LB_ADDSTRING) msg.lParam = lp ? hash_Ly((const char *)lp) : 0; else msg.lParam = lp; msg.descr = "listbox"; add_message(&msg); }
defwndproc_counter++; ret = CallWindowProcA(listbox_orig_proc, hwnd, message, wp, lp); defwndproc_counter--;
return ret;}
static void check_lb_state_dbg(HWND listbox, int count, int cur_sel, int caret_index, int top_index, int line){ LRESULT ret;
/* calling an orig proc helps to avoid unnecessary message logging */ ret = CallWindowProcA(listbox_orig_proc, listbox, LB_GETCOUNT, 0, 0); ok_(__FILE__, line)(ret == count, "expected count %d, got %ld\n", count, ret); ret = CallWindowProcA(listbox_orig_proc, listbox, LB_GETCURSEL, 0, 0); ok_(__FILE__, line)(ret == cur_sel, "expected cur sel %d, got %ld\n", cur_sel, ret); ret = CallWindowProcA(listbox_orig_proc, listbox, LB_GETCARETINDEX, 0, 0); ok_(__FILE__, line)(ret == caret_index || broken(cur_sel == -1 && caret_index == 0 && ret == -1), /* nt4 */ "expected caret index %d, got %ld\n", caret_index, ret); ret = CallWindowProcA(listbox_orig_proc, listbox, LB_GETTOPINDEX, 0, 0); ok_(__FILE__, line)(ret == top_index, "expected top index %d, got %ld\n", top_index, ret);}
static void test_listbox_messages(void){ HWND parent, listbox; LRESULT ret;
parent = CreateWindowExA(0, "TestParentClass", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 200, 200, 0, 0, 0, NULL); /* with LBS_HASSTRINGS */ listbox = CreateWindowExA(WS_EX_NOPARENTNOTIFY, "ListBox", NULL, WS_CHILD | LBS_NOTIFY | LBS_OWNERDRAWVARIABLE | LBS_HASSTRINGS | WS_VISIBLE, 10, 10, 80, 80, parent, (HMENU)ID_LISTBOX, 0, NULL); listbox_orig_proc = (WNDPROC)SetWindowLongPtrA(listbox, GWLP_WNDPROC, (ULONG_PTR)listbox_hook_proc);
check_lb_state(listbox, 0, LB_ERR, 0, 0);
flush_sequence();
log_all_parent_messages++;
ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 0"); ok(ret == 0, "expected 0, got %ld\n", ret); ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 1"); ok(ret == 1, "expected 1, got %ld\n", ret); ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 2"); ok(ret == 2, "expected 2, got %ld\n", ret);
ok_sequence(wm_lb_addstring_ownerdraw, "LB_ADDSTRING", FALSE); check_lb_state(listbox, 3, LB_ERR, 0, 0);
flush_sequence();
trace("selecting item 0\n"); ret = SendMessageA(listbox, LB_SETCURSEL, 0, 0); ok(ret == 0, "expected 0, got %ld\n", ret); ok_sequence(wm_lb_setcursel_0, "LB_SETCURSEL 0", FALSE ); check_lb_state(listbox, 3, 0, 0, 0); flush_sequence();
trace("selecting item 1\n"); ret = SendMessageA(listbox, LB_SETCURSEL, 1, 0); ok(ret == 1, "expected 1, got %ld\n", ret); ok_sequence(wm_lb_setcursel_1, "LB_SETCURSEL 1", FALSE ); check_lb_state(listbox, 3, 1, 1, 0);
trace("selecting item 2\n"); ret = SendMessageA(listbox, LB_SETCURSEL, 2, 0); ok(ret == 2, "expected 2, got %ld\n", ret); ok_sequence(wm_lb_setcursel_2, "LB_SETCURSEL 2", FALSE ); check_lb_state(listbox, 3, 2, 2, 0);
trace("clicking on item 0\n"); ret = SendMessageA(listbox, WM_LBUTTONDOWN, 0, MAKELPARAM(1, 1)); ok(ret == LB_OKAY, "expected LB_OKAY, got %ld\n", ret); ret = SendMessageA(listbox, WM_LBUTTONUP, 0, 0); ok(ret == LB_OKAY, "expected LB_OKAY, got %ld\n", ret); ok_sequence(wm_lb_click_0, "WM_LBUTTONDOWN 0", FALSE ); check_lb_state(listbox, 3, 0, 0, 0); flush_sequence();
trace("deleting item 0\n"); ret = SendMessageA(listbox, LB_DELETESTRING, 0, 0); ok(ret == 2, "expected 2, got %ld\n", ret); ok_sequence(wm_lb_deletestring, "LB_DELETESTRING 0", FALSE ); check_lb_state(listbox, 2, -1, 0, 0); flush_sequence();
trace("deleting item 0\n"); ret = SendMessageA(listbox, LB_DELETESTRING, 0, 0); ok(ret == 1, "expected 1, got %ld\n", ret); ok_sequence(wm_lb_deletestring, "LB_DELETESTRING 0", FALSE ); check_lb_state(listbox, 1, -1, 0, 0); flush_sequence();
trace("deleting item 0\n"); ret = SendMessageA(listbox, LB_DELETESTRING, 0, 0); ok(ret == 0, "expected 0, got %ld\n", ret); ok_sequence(wm_lb_deletestring_reset, "LB_DELETESTRING 0", FALSE ); check_lb_state(listbox, 0, -1, 0, 0); flush_sequence();
trace("deleting item 0\n"); ret = SendMessageA(listbox, LB_DELETESTRING, 0, 0); ok(ret == LB_ERR, "expected LB_ERR, got %ld\n", ret); check_lb_state(listbox, 0, -1, 0, 0); flush_sequence();
log_all_parent_messages--;
DestroyWindow(listbox);
/* with LBS_SORT and without LBS_HASSTRINGS */ listbox = CreateWindowExA(WS_EX_NOPARENTNOTIFY, "ListBox", NULL, WS_CHILD | LBS_NOTIFY | LBS_OWNERDRAWVARIABLE | LBS_SORT | WS_VISIBLE, 10, 10, 80, 80, parent, (HMENU)ID_LISTBOX, 0, NULL); listbox_orig_proc = (WNDPROC)SetWindowLongPtrA(listbox, GWLP_WNDPROC, (ULONG_PTR)listbox_hook_proc);
check_lb_state(listbox, 0, LB_ERR, 0, 0);
flush_sequence();
log_all_parent_messages++;
ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 0"); ok(ret == 0, "expected 0, got %ld\n", ret); ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 1"); ok(ret == 1, "expected 1, got %ld\n", ret); ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 2"); ok(ret == 2, "expected 2, got %ld\n", ret);
ok_sequence(wm_lb_addstring_sort_ownerdraw, "LB_ADDSTRING", FALSE); check_lb_state(listbox, 3, LB_ERR, 0, 0);
log_all_parent_messages--;
DestroyWindow(listbox);
/* with LBS_HASSTRINGS */ listbox = CreateWindowExA(WS_EX_NOPARENTNOTIFY, "ListBox", NULL, WS_CHILD | LBS_NOTIFY | LBS_HASSTRINGS | WS_VISIBLE, 10, 10, 80, 80, parent, (HMENU)ID_LISTBOX, 0, NULL); listbox_orig_proc = (WNDPROC)SetWindowLongPtrA(listbox, GWLP_WNDPROC, (ULONG_PTR)listbox_hook_proc);
check_lb_state(listbox, 0, LB_ERR, 0, 0);
flush_sequence();
log_all_parent_messages++;
ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 2"); ok(ret == 0, "expected 0, got %ld\n", ret); ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 0"); ok(ret == 1, "expected 1, got %ld\n", ret); ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 1"); ok(ret == 2, "expected 2, got %ld\n", ret);
ok_sequence(wm_lb_addstring, "LB_ADDSTRING", FALSE); check_lb_state(listbox, 3, LB_ERR, 0, 0);
log_all_parent_messages--;
DestroyWindow(listbox);
/* with LBS_HASSTRINGS and LBS_SORT */ listbox = CreateWindowExA(WS_EX_NOPARENTNOTIFY, "ListBox", NULL, WS_CHILD | LBS_NOTIFY | LBS_HASSTRINGS | LBS_SORT | WS_VISIBLE, 10, 10, 80, 80, parent, (HMENU)ID_LISTBOX, 0, NULL); listbox_orig_proc = (WNDPROC)SetWindowLongPtrA(listbox, GWLP_WNDPROC, (ULONG_PTR)listbox_hook_proc);
check_lb_state(listbox, 0, LB_ERR, 0, 0);
flush_sequence();
log_all_parent_messages++;
ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 2"); ok(ret == 0, "expected 0, got %ld\n", ret); ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 0"); ok(ret == 0, "expected 0, got %ld\n", ret); ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 1"); ok(ret == 1, "expected 1, got %ld\n", ret);
ok_sequence(wm_lb_addstring, "LB_ADDSTRING", FALSE); check_lb_state(listbox, 3, LB_ERR, 0, 0);
log_all_parent_messages--;
DestroyWindow(listbox); DestroyWindow(parent);}
/*************************** Menu test ******************************/static const struct message wm_popup_menu_1[] ={ { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'E', 0x20000001 }, { WM_SYSKEYDOWN, sent|wparam|lparam, 'E', 0x20000001 }, { WM_SYSCHAR, sent|wparam|lparam, 'e', 0x20000001 }, { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_KEYMENU, 'e' }, { WM_ENTERMENULOOP, sent|wparam|lparam, 0, 0 }, { WM_INITMENU, sent|lparam, 0, 0 }, { WM_MENUSELECT, sent|wparam, MAKEWPARAM(1,MF_HILITE|MF_POPUP) }, { WM_INITMENUPOPUP, sent|lparam, 0, 1 }, { HCBT_CREATEWND, hook|optional }, /* Win9x doesn't create a window */ { WM_MENUSELECT, sent|wparam, MAKEWPARAM(200,MF_HILITE) }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'E', 0xf0000001 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xd0000001 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RETURN, 0x10000001, 0, 0x40000000 }, { HCBT_DESTROYWND, hook|optional }, /* Win9x doesn't create a window */ { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, { WM_MENUSELECT, sent|wparam|lparam, MAKEWPARAM(0,0xffff), 0 }, { WM_EXITMENULOOP, sent|wparam|lparam, 0, 0 }, { WM_MENUCOMMAND, sent }, /* |wparam, 200 - Win9x */ { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RETURN, 0xc0000001 }, { WM_KEYUP, sent|wparam|lparam, VK_RETURN, 0xc0000001 }, { 0 }};static const struct message wm_popup_menu_2[] ={ { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'F', 0x20000001 }, { WM_SYSKEYDOWN, sent|wparam|lparam, 'F', 0x20000001 }, { WM_SYSCHAR, sent|wparam|lparam, 'f', 0x20000001 }, { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_KEYMENU, 'f' }, { WM_ENTERMENULOOP, sent|wparam|lparam, 0, 0 }, { WM_INITMENU, sent|lparam, 0, 0 }, { WM_MENUSELECT, sent|wparam, MAKEWPARAM(0,MF_HILITE|MF_POPUP) }, { WM_INITMENUPOPUP, sent|lparam, 0, 0 }, { WM_MENUSELECT, sent|wparam|optional, MAKEWPARAM(0,MF_HILITE|MF_POPUP) }, /* Win9x */ { WM_INITMENUPOPUP, sent|lparam|optional, 0, 0 }, /* Win9x */ { HCBT_CREATEWND, hook }, { WM_MENUSELECT, sent }, /*|wparam, MAKEWPARAM(0,MF_HILITE|MF_POPUP) - XP |wparam, MAKEWPARAM(100,MF_HILITE) - Win9x */ { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'F', 0xf0000001 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xd0000001 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RIGHT, 0x10000001 }, { WM_INITMENUPOPUP, sent|lparam|optional, 0, 0 }, /* Win9x doesn't send it */ { HCBT_CREATEWND, hook|optional }, /* Win9x doesn't send it */ { WM_MENUSELECT, sent|wparam|optional, MAKEWPARAM(100,MF_HILITE) }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RIGHT, 0xd0000001 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RETURN, 0x10000001 }, { HCBT_DESTROYWND, hook }, { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, { HCBT_DESTROYWND, hook|optional }, /* Win9x doesn't send it */ { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, { WM_MENUSELECT, sent|wparam|lparam, MAKEWPARAM(0,0xffff), 0 }, { WM_EXITMENULOOP, sent|wparam|lparam, 0, 0 }, { WM_MENUCOMMAND, sent }, /* |wparam, 100 - Win9x */ { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RETURN, 0xc0000001 }, { WM_KEYUP, sent|wparam|lparam, VK_RETURN, 0xc0000001 }, { 0 }};static const struct message wm_popup_menu_3[] ={ { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'F', 0x20000001 }, { WM_SYSKEYDOWN, sent|wparam|lparam, 'F', 0x20000001 }, { WM_SYSCHAR, sent|wparam|lparam, 'f', 0x20000001 }, { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_KEYMENU, 'f' }, { WM_ENTERMENULOOP, sent|wparam|lparam, 0, 0 }, { WM_INITMENU, sent|lparam, 0, 0 }, { WM_MENUSELECT, sent|wparam, MAKEWPARAM(0,MF_HILITE|MF_POPUP) }, { WM_INITMENUPOPUP, sent|lparam, 0, 0 }, { WM_MENUSELECT, sent|wparam|optional, MAKEWPARAM(0,MF_HILITE|MF_POPUP) }, /* Win9x */ { WM_INITMENUPOPUP, sent|lparam|optional, 0, 0 }, /* Win9x */ { HCBT_CREATEWND, hook }, { WM_MENUSELECT, sent }, /*|wparam, MAKEWPARAM(0,MF_HILITE|MF_POPUP) - XP |wparam, MAKEWPARAM(100,MF_HILITE) - Win9x */ { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'F', 0xf0000001 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xd0000001 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RIGHT, 0x10000001 }, { WM_INITMENUPOPUP, sent|lparam|optional, 0, 0 }, /* Win9x doesn't send it */ { HCBT_CREATEWND, hook|optional }, /* Win9x doesn't send it */ { WM_MENUSELECT, sent|wparam|optional, MAKEWPARAM(100,MF_HILITE) }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RIGHT, 0xd0000001 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RETURN, 0x10000001 }, { HCBT_DESTROYWND, hook }, { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, { HCBT_DESTROYWND, hook|optional }, /* Win9x doesn't send it */ { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, { WM_MENUSELECT, sent|wparam|lparam, MAKEWPARAM(0,0xffff), 0 }, { WM_EXITMENULOOP, sent|wparam|lparam, 0, 0 }, { WM_COMMAND, sent|wparam|lparam, 100, 0 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RETURN, 0xc0000001 }, { WM_KEYUP, sent|wparam|lparam, VK_RETURN, 0xc0000001 }, { 0 }};
static const struct message wm_single_menu_item[] ={ { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'Q', 0x20000001 }, { WM_SYSKEYDOWN, sent|wparam|lparam, 'Q', 0x20000001 }, { WM_SYSCHAR, sent|wparam|lparam, 'q', 0x20000001 }, { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_KEYMENU, 'q' }, { WM_ENTERMENULOOP, sent|wparam|lparam, 0, 0 }, { WM_INITMENU, sent|lparam, 0, 0 }, { WM_MENUSELECT, sent|wparam|optional, MAKEWPARAM(300,MF_HILITE) }, { WM_MENUSELECT, sent|wparam|lparam, MAKEWPARAM(0,0xffff), 0 }, { WM_EXITMENULOOP, sent|wparam|lparam, 0, 0 }, { WM_MENUCOMMAND, sent }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'Q', 0xe0000001 }, { WM_SYSKEYUP, sent|wparam|lparam, 'Q', 0xe0000001 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
{ HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_ESCAPE, 1 }, { WM_KEYDOWN, sent|wparam|lparam, VK_ESCAPE, 1 }, { WM_CHAR, sent|wparam|lparam, VK_ESCAPE, 0x00000001 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_ESCAPE, 0xc0000001 }, { WM_KEYUP, sent|wparam|lparam, VK_ESCAPE, 0xc0000001 }, { 0 }};
static LRESULT WINAPI parent_menu_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp){ if (message == WM_ENTERIDLE || message == WM_INITMENU || message == WM_INITMENUPOPUP || message == WM_MENUSELECT || message == WM_PARENTNOTIFY || message == WM_ENTERMENULOOP || message == WM_EXITMENULOOP || message == WM_UNINITMENUPOPUP || message == WM_KEYDOWN || message == WM_KEYUP || message == WM_CHAR || message == WM_SYSKEYDOWN || message == WM_SYSKEYUP || message == WM_SYSCHAR || message == WM_COMMAND || message == WM_MENUCOMMAND) { struct recvd_message msg;
msg.hwnd = hwnd; msg.message = message; msg.flags = sent|wparam|lparam; msg.wParam = wp; msg.lParam = lp; msg.descr = "parent_menu_proc"; add_message(&msg); }
return DefWindowProcA(hwnd, message, wp, lp);}
static void set_menu_style(HMENU hmenu, DWORD style){ MENUINFO mi; BOOL ret;
mi.cbSize = sizeof(mi); mi.fMask = MIM_STYLE; mi.dwStyle = style; SetLastError(0xdeadbeef); ret = pSetMenuInfo(hmenu, &mi); ok(ret, "SetMenuInfo error %u\n", GetLastError());}
static DWORD get_menu_style(HMENU hmenu){ MENUINFO mi; BOOL ret;
mi.cbSize = sizeof(mi); mi.fMask = MIM_STYLE; mi.dwStyle = 0; SetLastError(0xdeadbeef); ret = pGetMenuInfo(hmenu, &mi); ok(ret, "GetMenuInfo error %u\n", GetLastError());
return mi.dwStyle;}
static void test_menu_messages(void){ MSG msg; WNDCLASSA cls; HMENU hmenu, hmenu_popup; HWND hwnd; DWORD style;
if (!pGetMenuInfo || !pSetMenuInfo) { win_skip("GetMenuInfo and/or SetMenuInfo are not available\n"); return; } cls.style = 0; cls.lpfnWndProc = parent_menu_proc; cls.cbClsExtra = 0; cls.cbWndExtra = 0; cls.hInstance = GetModuleHandleA(0); cls.hIcon = 0; cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); cls.hbrBackground = GetStockObject(WHITE_BRUSH); cls.lpszMenuName = NULL; cls.lpszClassName = "TestMenuClass"; UnregisterClassA(cls.lpszClassName, cls.hInstance); if (!RegisterClassA(&cls)) assert(0);
SetLastError(0xdeadbeef); hwnd = CreateWindowExA(0, "TestMenuClass", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 200, 200, 0, 0, 0, NULL); ok(hwnd != 0, "LoadMenuA error %u\n", GetLastError());
SetLastError(0xdeadbeef); hmenu = LoadMenuA(GetModuleHandleA(NULL), MAKEINTRESOURCEA(1)); ok(hmenu != 0, "LoadMenuA error %u\n", GetLastError());
SetMenu(hwnd, hmenu); SetForegroundWindow( hwnd ); flush_events();
set_menu_style(hmenu, MNS_NOTIFYBYPOS); style = get_menu_style(hmenu); ok(style == MNS_NOTIFYBYPOS, "expected MNS_NOTIFYBYPOS, got %u\n", style);
hmenu_popup = GetSubMenu(hmenu, 0); ok(hmenu_popup != 0, "GetSubMenu returned 0 for submenu 0\n"); style = get_menu_style(hmenu_popup); ok(style == 0, "expected 0, got %u\n", style);
hmenu_popup = GetSubMenu(hmenu_popup, 0); ok(hmenu_popup != 0, "GetSubMenu returned 0 for submenu 0\n"); style = get_menu_style(hmenu_popup); ok(style == 0, "expected 0, got %u\n", style);
/* Alt+E, Enter */ trace("testing a popup menu command\n"); flush_sequence(); keybd_event(VK_MENU, 0, 0, 0); keybd_event('E', 0, 0, 0); keybd_event('E', 0, KEYEVENTF_KEYUP, 0); keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); keybd_event(VK_RETURN, 0, 0, 0); keybd_event(VK_RETURN, 0, KEYEVENTF_KEYUP, 0); while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessageA(&msg); } if (!sequence_cnt) /* we didn't get any message */ { skip( "queuing key events not supported\n" ); goto done; } /* win98 queues only a WM_KEYUP and doesn't start menu tracking */ if (sequence[0].message == WM_KEYUP && sequence[0].wParam == VK_MENU) { win_skip( "menu tracking through VK_MENU not supported\n" ); goto done; } ok_sequence(wm_popup_menu_1, "popup menu command", FALSE);
/* Alt+F, Right, Enter */ trace("testing submenu of a popup menu command\n"); flush_sequence(); keybd_event(VK_MENU, 0, 0, 0); keybd_event('F', 0, 0, 0); keybd_event('F', 0, KEYEVENTF_KEYUP, 0); keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); keybd_event(VK_RIGHT, 0, 0, 0); keybd_event(VK_RIGHT, 0, KEYEVENTF_KEYUP, 0); keybd_event(VK_RETURN, 0, 0, 0); keybd_event(VK_RETURN, 0, KEYEVENTF_KEYUP, 0); while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessageA(&msg); } ok_sequence(wm_popup_menu_2, "submenu of a popup menu command", FALSE);
trace("testing single menu item command\n"); flush_sequence(); keybd_event(VK_MENU, 0, 0, 0); keybd_event('Q', 0, 0, 0); keybd_event('Q', 0, KEYEVENTF_KEYUP, 0); keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); keybd_event(VK_ESCAPE, 0, 0, 0); keybd_event(VK_ESCAPE, 0, KEYEVENTF_KEYUP, 0); while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessageA(&msg); } ok_sequence(wm_single_menu_item, "single menu item command", FALSE);
set_menu_style(hmenu, 0); style = get_menu_style(hmenu); ok(style == 0, "expected 0, got %u\n", style);
hmenu_popup = GetSubMenu(hmenu, 0); ok(hmenu_popup != 0, "GetSubMenu returned 0 for submenu 0\n"); set_menu_style(hmenu_popup, MNS_NOTIFYBYPOS); style = get_menu_style(hmenu_popup); ok(style == MNS_NOTIFYBYPOS, "expected MNS_NOTIFYBYPOS, got %u\n", style);
hmenu_popup = GetSubMenu(hmenu_popup, 0); ok(hmenu_popup != 0, "GetSubMenu returned 0 for submenu 0\n"); style = get_menu_style(hmenu_popup); ok(style == 0, "expected 0, got %u\n", style);
/* Alt+F, Right, Enter */ trace("testing submenu of a popup menu command\n"); flush_sequence(); keybd_event(VK_MENU, 0, 0, 0); keybd_event('F', 0, 0, 0); keybd_event('F', 0, KEYEVENTF_KEYUP, 0); keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); keybd_event(VK_RIGHT, 0, 0, 0); keybd_event(VK_RIGHT, 0, KEYEVENTF_KEYUP, 0); keybd_event(VK_RETURN, 0, 0, 0); keybd_event(VK_RETURN, 0, KEYEVENTF_KEYUP, 0); while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessageA(&msg); } ok_sequence(wm_popup_menu_3, "submenu of a popup menu command", FALSE);
done: DestroyWindow(hwnd); DestroyMenu(hmenu);}
static void test_paintingloop(void){ HWND hwnd;
paint_loop_done = FALSE; hwnd = CreateWindowExA(0x0,"PaintLoopWindowClass", "PaintLoopWindowClass",WS_OVERLAPPEDWINDOW, 100, 100, 100, 100, 0, 0, 0, NULL ); ok(hwnd != 0, "PaintLoop window error %u\n", GetLastError()); ShowWindow(hwnd,SW_NORMAL); SetFocus(hwnd);
while (!paint_loop_done) { MSG msg; if (PeekMessageA(&msg, 0, 0, 0, 1)) { TranslateMessage(&msg); DispatchMessageA(&msg); } } DestroyWindow(hwnd);}
static const struct message NCRBUTTONDOWNSeq[] ={ { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 }, { WM_CAPTURECHANGED, sent }, { WM_CONTEXTMENU, sent, /*hwnd*/0, -1 }, { 0 }};
static const struct message NCXBUTTONUPSeq1[] ={ { WM_APPCOMMAND, sent|lparam, /*hwnd*/0, MAKELPARAM(0, FAPPCOMMAND_MOUSE | APPCOMMAND_BROWSER_BACKWARD) }, { 0 }};
static const struct message NCXBUTTONUPSeq2[] ={ { WM_APPCOMMAND, sent|lparam, /*hwnd*/0, MAKELPARAM(0, FAPPCOMMAND_MOUSE | APPCOMMAND_BROWSER_FORWARD) }, { 0 }};
/* DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0) to minimized visible window */static const struct message WmRestoreMinimizedOverlappedSeq[] ={ { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_RESTORE, 0 }, { HCBT_MINMAX, hook }, { WM_QUERYOPEN, sent }, { WM_GETTEXT, sent|optional }, { WM_NCACTIVATE, sent|optional }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, { WM_WINDOWPOSCHANGED, sent|optional }, { WM_WINDOWPOSCHANGING, sent|optional }, { WM_GETMINMAXINFO, sent|defwinproc }, { WM_NCCALCSIZE, sent|optional }, { WM_NCPAINT, sent|optional }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent|optional }, { WM_WINDOWPOSCHANGED, sent|optional }, { HCBT_ACTIVATE, hook }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE }, { WM_ACTIVATEAPP, sent|wparam, TRUE }, { WM_NCACTIVATE, sent|wparam, TRUE }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ACTIVATE, sent|wparam, TRUE }, { HCBT_SETFOCUS, hook }, { WM_SETFOCUS, sent|defwinproc }, { WM_NCPAINT, sent }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_FRAMECHANGED|SWP_STATECHANGED }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|defwinproc }, { WM_NCCALCSIZE, sent|optional }, { WM_NCPAINT, sent|optional }, { WM_ERASEBKGND, sent|optional }, { WM_ACTIVATE, sent|wparam, TRUE }, { WM_SYNCPAINT, sent|optional }, { WM_PAINT, sent }, { 0 }};
static struct message WmContextMenuSeq[] = { { WM_CONTEXTMENU, sent|wparam, 0 }, /* wparams set in the code */ { WM_CONTEXTMENU, sent|wparam|defwinproc, 0 }, { WM_CONTEXTMENU, sent|wparam|defwinproc, 0 }, { 0 }};
struct rbuttonup_thread_data{ HWND hwnd; HANDLE wndproc_finished;};
static DWORD CALLBACK post_rbuttonup_msg( void *arg ){ struct rbuttonup_thread_data *data = arg; DWORD ret;
ret = WaitForSingleObject( data->wndproc_finished, 500 ); todo_wine ok( ret == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", ret ); if( ret == WAIT_OBJECT_0 ) return 0;
PostMessageA( data->hwnd, WM_RBUTTONUP, 0, 0 ); return 0;}
static void test_defwinproc(void){ HWND hwnd, child[3]; MSG msg; BOOL gotwmquit = FALSE; POINT pos; RECT rect; INT x, y; LRESULT res; struct rbuttonup_thread_data data; char buffA[64]; HANDLE thread;
hwnd = CreateWindowExA(0, "TestWindowClass", "test_defwndproc", WS_VISIBLE | WS_CAPTION | WS_OVERLAPPEDWINDOW, 0,0,500,100,0,0,0, NULL); assert(hwnd); flush_events();
buffA[0] = 0; GetWindowTextA(hwnd, buffA, ARRAY_SIZE(buffA)); ok(!strcmp(buffA, "test_defwndproc"), "unexpected window text, %s\n", buffA);
/* Zero high word of the lParam */ res = DefWindowProcA(hwnd, WM_SETTEXT, 0, 0x1234); ok(res == 0, "WM_SETTEXT was expected to fail, %ld\n", res);
GetWindowTextA(hwnd, buffA, ARRAY_SIZE(buffA)); ok(!strcmp(buffA, "test_defwndproc"), "unexpected window text, %s\n", buffA);
res = DefWindowProcW(hwnd, WM_SETTEXT, 0, 0x1234); ok(res == 0, "WM_SETTEXT was expected to fail, %ld\n", res);
GetWindowTextA(hwnd, buffA, ARRAY_SIZE(buffA)); ok(!strcmp(buffA, "test_defwndproc"), "unexpected window text, %s\n", buffA);
ShowWindow(hwnd, SW_MINIMIZE); flush_events(); flush_sequence();
DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0); flush_events(); ok_sequence(WmRestoreMinimizedOverlappedSeq, "DefWindowProcA(SC_RESTORE):overlapped", TRUE); flush_sequence();
child[0] = CreateWindowExA(0, "TestWindowClass", "1st child", WS_VISIBLE | WS_CHILD, 0,0,500,100, hwnd, 0, 0, NULL); child[1] = CreateWindowExA(0, "TestWindowClass", "2nd child", WS_VISIBLE | WS_CHILD, 0,0,500,100, child[0], 0, 0, NULL); child[2] = CreateWindowExA(0, "TestWindowClass", "3rd child", WS_VISIBLE | WS_CHILD, 0,0,500,100, child[1], 0, 0, NULL); flush_events(); flush_sequence(); test_context_menu = TRUE; DefWindowProcA(child[2], WM_CONTEXTMENU, 0xcafe, 0); test_context_menu = FALSE; WmContextMenuSeq[0].wParam = (WPARAM)child[2]; WmContextMenuSeq[1].wParam = (WPARAM)child[1]; WmContextMenuSeq[2].wParam = (WPARAM)child[0]; ok_sequence(WmContextMenuSeq, "DefWindowProcA(WM_CONTEXTMENU)", FALSE); DestroyWindow(child[0]);
GetCursorPos(&pos); GetWindowRect(hwnd, &rect); x = (rect.left+rect.right) / 2; y = rect.top + GetSystemMetrics(SM_CYFRAME) + 1; SetCursorPos(x, y); flush_events(); res = DefWindowProcA( hwnd, WM_NCHITTEST, 0, MAKELPARAM(x, y)); ok(res == HTCAPTION, "WM_NCHITTEST returned %ld\n", res);
mouse_event( MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0 ); mouse_event( MOUSEEVENTF_LEFTUP, 0, 0, 0, 0 ); flush_events();
flush_sequence(); mouse_event( MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0 ); /* workaround for missing support for clicking on window frame */ data.hwnd = hwnd; data.wndproc_finished = CreateEventA( NULL, FALSE, FALSE, NULL ); thread = CreateThread( NULL, 0, post_rbuttonup_msg, (void*)&data, 0, NULL );
DefWindowProcA( hwnd, WM_NCRBUTTONDOWN, HTCAPTION, MAKELPARAM(x, y)); ok_sequence(NCRBUTTONDOWNSeq, "WM_NCRBUTTONDOWN on caption", FALSE);
res = DefWindowProcA(hwnd, WM_NCXBUTTONUP, 0, MAKELPARAM(x, y)); ok(!res, "WM_NCXBUTTONUP returned %ld\n", res); ok_sequence(WmEmptySeq, "WM_NCXBUTTONUP without button", FALSE);
res = DefWindowProcA(hwnd, WM_NCXBUTTONUP, MAKEWPARAM(0, XBUTTON1), MAKELPARAM(x, y)); ok(!res, "WM_NCXBUTTONUP returned %ld\n", res); ok_sequence(NCXBUTTONUPSeq1, "WM_NCXBUTTONUP with XBUTTON1", FALSE);
res = DefWindowProcA(hwnd, WM_NCXBUTTONUP, MAKEWPARAM(0, XBUTTON2), MAKELPARAM(x, y)); ok(!res, "WM_NCXBUTTONUP returned %ld\n", res); ok_sequence(NCXBUTTONUPSeq2, "WM_NCXBUTTONUP with XBUTTON2", FALSE);
res = DefWindowProcA(hwnd, WM_NCXBUTTONUP, MAKEWPARAM(0, 3), MAKELPARAM(x, y)); ok(!res, "WM_NCXBUTTONUP returned %ld\n", res); ok_sequence(WmEmptySeq, "WM_NCXBUTTONUP with invalid button", FALSE);
SetEvent( data.wndproc_finished ); WaitForSingleObject( thread, 1000 ); CloseHandle( data.wndproc_finished ); CloseHandle( thread );
SetCursorPos(pos.x, pos.y);
DefWindowProcA( hwnd, WM_ENDSESSION, 1, 0); while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) { if( msg.message == WM_QUIT) gotwmquit = TRUE; DispatchMessageA( &msg ); } ok(!gotwmquit, "Unexpected WM_QUIT message!\n"); DestroyWindow( hwnd);}
static void test_desktop_winproc(void){ HINSTANCE instance = GetModuleHandleA(NULL); RECT rect, default_rect; WNDPROC desktop_proc; char buffer[256]; WNDCLASSA cls; LRESULT res; HWND hwnd; BOOL ret;
ret = GetClassInfoA(instance, (const CHAR *)MAKEINTATOM(32769), &cls); ok(ret, "Failed to get desktop class.\n"); desktop_proc = cls.lpfnWndProc;
memset(&cls, 0, sizeof(cls)); cls.lpfnWndProc = desktop_proc; cls.hInstance = instance; cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); cls.hbrBackground = GetStockObject(WHITE_BRUSH); cls.lpszClassName = "TestDesktopClass"; ret = !!RegisterClassA(&cls); ok(ret, "Failed to register class.\n");
hwnd = CreateWindowExA(0, cls.lpszClassName, "test_desktop_wndproc", WS_VISIBLE | WS_CAPTION | WS_OVERLAPPEDWINDOW, 0, 0, 500, 100, 0, 0, 0, NULL); if (!hwnd) /* win2003 */ { skip("Failed to create window with desktop window procedure.\n"); goto out_unregister; }
memset(&cls, 0, sizeof(cls)); ret = GetClassInfoA(instance, "TestDesktopClass", &cls); ok(ret, "Failed to get class info.\n"); ok(cls.lpfnWndProc == desktop_proc, "Got %p, expected %p.\n", cls.lpfnWndProc, desktop_proc);
GetWindowTextA(hwnd, buffer, ARRAY_SIZE(buffer)); todo_wine ok(!strcmp(buffer, "test_desktop_wndproc"), "Got unexpected window text: %s.\n", buffer);
res = CallWindowProcA(desktop_proc, hwnd, WM_SETTEXT, 0, (LPARAM)"test"); ok(res == TRUE, "Failed to set text, %ld.\n", res); GetWindowTextA(hwnd, buffer, ARRAY_SIZE(buffer)); ok(!strcmp(buffer, "test"), "Got unexpected window text: %s.\n", buffer);
SetRect(&default_rect, 0, 0, 100, 100); res = DefWindowProcW(hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&default_rect); ok(!res, "Got unexpected result %ld.\n", res);
SetRect(&rect, 0, 0, 100, 100); res = CallWindowProcA(desktop_proc, hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&rect); ok(!res, "Got unexpected result %ld.\n", res); todo_wine ok(EqualRect(&rect, &default_rect), "rect Got %s, expected %s.\n", wine_dbgstr_rect(&rect), wine_dbgstr_rect(&default_rect));
DestroyWindow(hwnd);
out_unregister: UnregisterClassA("TestDesktopClass", instance);}
#define clear_clipboard(hwnd) clear_clipboard_(__LINE__, (hwnd))static void clear_clipboard_(int line, HWND hWnd){ BOOL succ; succ = OpenClipboard(hWnd); ok_(__FILE__, line)(succ, "OpenClipboard failed, err=%u\n", GetLastError()); succ = EmptyClipboard(); ok_(__FILE__, line)(succ, "EmptyClipboard failed, err=%u\n", GetLastError()); succ = CloseClipboard(); ok_(__FILE__, line)(succ, "CloseClipboard failed, err=%u\n", GetLastError());}
#define expect_HWND(expected, got) expect_HWND_(__LINE__, (expected), (got))static void expect_HWND_(int line, HWND expected, HWND got){ ok_(__FILE__, line)(got==expected, "Expected %p, got %p\n", expected, got);}
static WNDPROC pOldViewerProc;
static LRESULT CALLBACK recursive_viewer_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){ static BOOL recursion_guard;
if (message == WM_DRAWCLIPBOARD && !recursion_guard) { recursion_guard = TRUE; clear_clipboard(hWnd); recursion_guard = FALSE; } return CallWindowProcA(pOldViewerProc, hWnd, message, wParam, lParam);}
static void test_clipboard_viewers(void){ static struct message wm_change_cb_chain[] = { { WM_CHANGECBCHAIN, sent|wparam|lparam, 0, 0 }, { 0 } }; static const struct message wm_clipboard_destroyed[] = { { WM_DESTROYCLIPBOARD, sent|wparam|lparam, 0, 0 }, { 0 } }; static struct message wm_clipboard_changed[] = { { WM_DRAWCLIPBOARD, sent|wparam|lparam, 0, 0 }, { 0 } }; static struct message wm_clipboard_changed_and_owned[] = { { WM_DESTROYCLIPBOARD, sent|wparam|lparam, 0, 0 }, { WM_DRAWCLIPBOARD, sent|wparam|lparam, 0, 0 }, { 0 } };
HINSTANCE hInst = GetModuleHandleA(NULL); HWND hWnd1, hWnd2, hWnd3; HWND hOrigViewer; HWND hRet;
hWnd1 = CreateWindowExA(0, "TestWindowClass", "Clipboard viewer test wnd 1", WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, GetDesktopWindow(), NULL, hInst, NULL); hWnd2 = CreateWindowExA(0, "SimpleWindowClass", "Clipboard viewer test wnd 2", WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, GetDesktopWindow(), NULL, hInst, NULL); hWnd3 = CreateWindowExA(0, "SimpleWindowClass", "Clipboard viewer test wnd 3", WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, GetDesktopWindow(), NULL, hInst, NULL); trace("clipbd viewers: hWnd1=%p, hWnd2=%p, hWnd3=%p\n", hWnd1, hWnd2, hWnd3); assert(hWnd1 && hWnd2 && hWnd3);
CountClipboardFormats(); /* Ensure that we do not have an X11 update to the clipboard */ flush_sequence();
/* Test getting the clipboard viewer and setting the viewer to NULL. */ hOrigViewer = GetClipboardViewer(); hRet = SetClipboardViewer(NULL); ok_sequence(WmEmptySeq, "set viewer to NULL", FALSE); expect_HWND(hOrigViewer, hRet); expect_HWND(NULL, GetClipboardViewer());
/* Test registering hWnd1 as a viewer. */ hRet = SetClipboardViewer(hWnd1); wm_clipboard_changed[0].wParam = (WPARAM) GetClipboardOwner(); ok_sequence(wm_clipboard_changed, "set viewer NULL->1", FALSE); expect_HWND(NULL, hRet); expect_HWND(hWnd1, GetClipboardViewer());
/* Test that changing the clipboard actually refreshes the registered viewer. */ clear_clipboard(hWnd1); wm_clipboard_changed[0].wParam = (WPARAM) GetClipboardOwner(); ok_sequence(wm_clipboard_changed, "clear clipbd (viewer=owner=1)", FALSE);
/* Again, but with different owner. */ clear_clipboard(hWnd2); wm_clipboard_changed_and_owned[1].wParam = (WPARAM) GetClipboardOwner(); ok_sequence(wm_clipboard_changed_and_owned, "clear clipbd (viewer=1, owner=2)", FALSE);
/* Test re-registering same window. */ hRet = SetClipboardViewer(hWnd1); wm_clipboard_changed[0].wParam = (WPARAM) GetClipboardOwner(); ok_sequence(wm_clipboard_changed, "set viewer 1->1", FALSE); expect_HWND(hWnd1, hRet); expect_HWND(hWnd1, GetClipboardViewer());
/* Test ChangeClipboardChain. */ ChangeClipboardChain(hWnd2, hWnd3); wm_change_cb_chain[0].wParam = (WPARAM) hWnd2; wm_change_cb_chain[0].lParam = (LPARAM) hWnd3; ok_sequence(wm_change_cb_chain, "change chain (viewer=1, remove=2, next=3)", FALSE); expect_HWND(hWnd1, GetClipboardViewer());
ChangeClipboardChain(hWnd2, NULL); wm_change_cb_chain[0].wParam = (WPARAM) hWnd2; wm_change_cb_chain[0].lParam = 0; ok_sequence(wm_change_cb_chain, "change chain (viewer=1, remove=2, next=NULL)", FALSE); expect_HWND(hWnd1, GetClipboardViewer());
ChangeClipboardChain(NULL, hWnd2); ok_sequence(WmEmptySeq, "change chain (viewer=1, remove=NULL, next=2)", FALSE); expect_HWND(hWnd1, GetClipboardViewer());
/* Actually change clipboard viewer with ChangeClipboardChain. */ ChangeClipboardChain(hWnd1, hWnd2); ok_sequence(WmEmptySeq, "change chain (viewer=remove=1, next=2)", FALSE); expect_HWND(hWnd2, GetClipboardViewer());
/* Test that no refresh messages are sent when viewer has unregistered. */ clear_clipboard(hWnd2); ok_sequence(WmEmptySeq, "clear clipd (viewer=2, owner=1)", FALSE);
/* Register hWnd1 again. */ ChangeClipboardChain(hWnd2, hWnd1); ok_sequence(WmEmptySeq, "change chain (viewer=remove=2, next=1)", FALSE); expect_HWND(hWnd1, GetClipboardViewer());
/* Subclass hWnd1 so that when it receives a WM_DRAWCLIPBOARD message, it * changes the clipboard. When this happens, the system shouldn't send * another WM_DRAWCLIPBOARD (as this could cause an infinite loop). */ pOldViewerProc = (WNDPROC) SetWindowLongPtrA(hWnd1, GWLP_WNDPROC, (LONG_PTR) recursive_viewer_proc); clear_clipboard(hWnd2); /* The clipboard owner is changed in recursive_viewer_proc: */ wm_clipboard_changed[0].wParam = (WPARAM) hWnd2; ok_sequence(wm_clipboard_changed, "recursive clear clipbd (viewer=1, owner=2)", TRUE);
/* Test unregistering. */ ChangeClipboardChain(hWnd1, NULL); ok_sequence(WmEmptySeq, "change chain (viewer=remove=1, next=NULL)", FALSE); expect_HWND(NULL, GetClipboardViewer());
clear_clipboard(hWnd1); ok_sequence(wm_clipboard_destroyed, "clear clipbd (no viewer, owner=1)", FALSE);
DestroyWindow(hWnd1); DestroyWindow(hWnd2); DestroyWindow(hWnd3); SetClipboardViewer(hOrigViewer);}
static void test_PostMessage(void){ static const struct { HWND hwnd; BOOL ret; } data[] = { { HWND_TOP /* 0 */, TRUE }, { HWND_BROADCAST, TRUE }, { HWND_BOTTOM, TRUE }, { HWND_TOPMOST, TRUE }, { HWND_NOTOPMOST, FALSE }, { HWND_MESSAGE, FALSE }, { (HWND)0xdeadbeef, FALSE } }; int i; HWND hwnd; BOOL ret; MSG msg; static const WCHAR staticW[] = {'s','t','a','t','i','c',0};
SetLastError(0xdeadbeef); hwnd = CreateWindowExW(0, staticW, NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL); if (!hwnd && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) { win_skip("Skipping some PostMessage tests on Win9x/WinMe\n"); return; } assert(hwnd);
flush_events();
PostMessageA(hwnd, WM_USER+1, 0x1234, 0x5678); PostMessageA(0, WM_USER+2, 0x5678, 0x1234);
for (i = 0; i < ARRAY_SIZE(data); i++) { memset(&msg, 0xab, sizeof(msg)); ret = PeekMessageA(&msg, data[i].hwnd, 0, 0, PM_NOREMOVE); ok(ret == data[i].ret, "%d: hwnd %p expected %d, got %d\n", i, data[i].hwnd, data[i].ret, ret); if (data[i].ret) { if (data[i].hwnd) ok(ret && msg.hwnd == 0 && msg.message == WM_USER+2 && msg.wParam == 0x5678 && msg.lParam == 0x1234, "%d: got ret %d hwnd %p msg %04x wParam %08lx lParam %08lx instead of TRUE/0/WM_USER+2/0x5678/0x1234\n", i, ret, msg.hwnd, msg.message, msg.wParam, msg.lParam); else ok(ret && msg.hwnd == hwnd && msg.message == WM_USER+1 && msg.wParam == 0x1234 && msg.lParam == 0x5678, "%d: got ret %d hwnd %p msg %04x wParam %08lx lParam %08lx instead of TRUE/%p/WM_USER+1/0x1234/0x5678\n", i, ret, msg.hwnd, msg.message, msg.wParam, msg.lParam, msg.hwnd); } }
DestroyWindow(hwnd); flush_events();}
static LPARAM g_broadcast_lparam;static LRESULT WINAPI broadcast_test_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
if (wParam == 0xbaadbeef) g_broadcast_lparam = wParam; else g_broadcast_lparam = 0;
return CallWindowProcA(oldproc, hwnd, message, wParam, lParam);}
static void test_broadcast(void){ static const UINT messages[] = { WM_USER-1, WM_USER, WM_USER+1, 0xc000-1, 0xc000, /* lowest possible atom returned by RegisterWindowMessage */ 0xffff, }; WNDPROC oldproc; unsigned int i; HWND hwnd;
hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0, 0, 0, 0, 0, 0, 0, NULL); ok(hwnd != NULL, "got %p\n", hwnd);
oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONG_PTR)broadcast_test_proc); SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc);
for (i = 0; i < ARRAY_SIZE(messages); i++) { BOOL ret; MSG msg;
flush_events(); while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) ;
/* post, broadcast */ ret = PostMessageA(HWND_BROADCAST, messages[i], 0, 0); ok(ret, "%d: got %d, error %d\n", i, ret, GetLastError());
memset(&msg, 0xab, sizeof(msg)); ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE); if (messages[i] < WM_USER || messages[i] >= 0xc000) { ok(ret, "%d: message %04x, got %d, error %d\n", i, messages[i], ret, GetLastError()); ok(msg.hwnd == hwnd, "%d: got %p\n", i, msg.hwnd); } else { ok(!ret, "%d: message %04x, got %d, error %d\n", i, messages[i], ret, GetLastError()); }
/* post, topmost */ ret = PostMessageA(HWND_TOPMOST, messages[i], 0, 0); ok(ret, "%d: got %d, error %d\n", i, ret, GetLastError());
memset(&msg, 0xab, sizeof(msg)); ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE); if (messages[i] < WM_USER || messages[i] >= 0xc000) { ok(ret, "%d: message %04x, got %d, error %d\n", i, messages[i], ret, GetLastError()); ok(msg.hwnd == hwnd, "%d: got %p\n", i, msg.hwnd); } else { ok(!ret, "%d: got %d, error %d\n", i, ret, GetLastError()); }
/* send, broadcast */ g_broadcast_lparam = 0xdead; ret = SendMessageTimeoutA(HWND_BROADCAST, messages[i], 0xbaadbeef, 0, SMTO_NORMAL, 2000, NULL); if (!ret && GetLastError() == ERROR_TIMEOUT) win_skip("broadcasting test %d, timeout\n", i); else { if (messages[i] < WM_USER || messages[i] >= 0xc000) { ok(g_broadcast_lparam == 0xbaadbeef, "%d: message %04x, got %#lx, error %d\n", i, messages[i], g_broadcast_lparam, GetLastError()); } else { ok(g_broadcast_lparam == 0xdead, "%d: message %04x, got %#lx, error %d\n", i, messages[i], g_broadcast_lparam, GetLastError()); } }
/* send, topmost */ g_broadcast_lparam = 0xdead; ret = SendMessageTimeoutA(HWND_TOPMOST, messages[i], 0xbaadbeef, 0, SMTO_NORMAL, 2000, NULL); if (!ret && GetLastError() == ERROR_TIMEOUT) win_skip("broadcasting test %d, timeout\n", i); else { if (messages[i] < WM_USER || messages[i] >= 0xc000) { ok(g_broadcast_lparam == 0xbaadbeef, "%d: message %04x, got %#lx, error %d\n", i, messages[i], g_broadcast_lparam, GetLastError()); } else { ok(g_broadcast_lparam == 0xdead, "%d: message %04x, got %#lx, error %d\n", i, messages[i], g_broadcast_lparam, GetLastError()); } } }
DestroyWindow(hwnd);}
static const struct{ DWORD exp, broken; BOOL todo;} wait_idle_expect[] ={/* 0 */ { WAIT_TIMEOUT, WAIT_TIMEOUT, FALSE }, { WAIT_TIMEOUT, 0, FALSE }, { WAIT_TIMEOUT, 0, FALSE }, { WAIT_TIMEOUT, WAIT_TIMEOUT, FALSE }, { WAIT_TIMEOUT, WAIT_TIMEOUT, FALSE },/* 5 */ { WAIT_TIMEOUT, 0, FALSE }, { WAIT_TIMEOUT, 0, FALSE }, { WAIT_TIMEOUT, WAIT_TIMEOUT, FALSE }, { 0, 0, FALSE }, { 0, 0, FALSE },/* 10 */ { 0, 0, FALSE }, { 0, 0, FALSE }, { 0, WAIT_TIMEOUT, FALSE }, { 0, 0, FALSE }, { 0, 0, FALSE },/* 15 */ { 0, 0, FALSE }, { WAIT_TIMEOUT, 0, FALSE }, { WAIT_TIMEOUT, 0, FALSE }, { WAIT_TIMEOUT, 0, FALSE }, { WAIT_TIMEOUT, 0, FALSE },/* 20 */ { WAIT_TIMEOUT, 0, FALSE },};
static DWORD CALLBACK do_wait_idle_child_thread( void *arg ){ MSG msg;
PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ); Sleep( 200 ); MsgWaitForMultipleObjects( 0, NULL, FALSE, 100, QS_ALLINPUT ); return 0;}
static void do_wait_idle_child( int arg ){ WNDCLASSA cls; MSG msg; HWND hwnd = 0; HANDLE thread; DWORD id; HANDLE start_event = OpenEventA( EVENT_ALL_ACCESS, FALSE, "test_WaitForInputIdle_start" ); HANDLE end_event = OpenEventA( EVENT_ALL_ACCESS, FALSE, "test_WaitForInputIdle_end" );
memset( &cls, 0, sizeof(cls) ); cls.lpfnWndProc = DefWindowProcA; cls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); cls.lpszClassName = "TestClass"; RegisterClassA( &cls );
PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ); /* create the msg queue */
ok( start_event != 0, "failed to create start event, error %u\n", GetLastError() ); ok( end_event != 0, "failed to create end event, error %u\n", GetLastError() );
switch (arg) { case 0: SetEvent( start_event ); break; case 1: SetEvent( start_event ); Sleep( 200 ); PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ); break; case 2: SetEvent( start_event ); Sleep( 200 ); PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ); PostThreadMessageA( GetCurrentThreadId(), WM_COMMAND, 0x1234, 0xabcd ); PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ); break; case 3: SetEvent( start_event ); Sleep( 200 ); SendMessageA( HWND_BROADCAST, WM_WININICHANGE, 0, 0 ); break; case 4: SetEvent( start_event ); Sleep( 200 ); hwnd = CreateWindowExA(0, "TestClass", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 10, 10, 0, 0, 0, NULL); while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE|PM_NOYIELD )) DispatchMessageA( &msg ); break; case 5: SetEvent( start_event ); Sleep( 200 ); hwnd = CreateWindowExA(0, "TestClass", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 10, 10, 0, 0, 0, NULL); while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); break; case 6: SetEvent( start_event ); Sleep( 200 ); hwnd = CreateWindowExA(0, "TestClass", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 10, 10, 0, 0, 0, NULL); while (PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE )) { GetMessageA( &msg, 0, 0, 0 ); DispatchMessageA( &msg ); } break; case 7: SetEvent( start_event ); Sleep( 200 ); hwnd = CreateWindowExA(0, "TestClass", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 10, 10, 0, 0, 0, NULL); SetTimer( hwnd, 3, 1, NULL ); Sleep( 200 ); while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE|PM_NOYIELD )) DispatchMessageA( &msg ); break; case 8: SetEvent( start_event ); Sleep( 200 ); PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ); MsgWaitForMultipleObjects( 0, NULL, FALSE, 100, QS_ALLINPUT ); break; case 9: SetEvent( start_event ); Sleep( 200 ); hwnd = CreateWindowExA(0, "TestClass", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 10, 10, 0, 0, 0, NULL); while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); for (;;) GetMessageA( &msg, 0, 0, 0 ); break; case 10: SetEvent( start_event ); Sleep( 200 ); hwnd = CreateWindowExA(0, "TestClass", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 10, 10, 0, 0, 0, NULL); SetTimer( hwnd, 3, 1, NULL ); Sleep( 200 ); while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); break; case 11: SetEvent( start_event ); Sleep( 200 ); return; /* exiting the process makes WaitForInputIdle return success too */ case 12: PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ); Sleep( 200 ); MsgWaitForMultipleObjects( 0, NULL, FALSE, 100, QS_ALLINPUT ); SetEvent( start_event ); break; case 13: SetEvent( start_event ); PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ); Sleep( 200 ); thread = CreateThread( NULL, 0, do_wait_idle_child_thread, NULL, 0, &id ); WaitForSingleObject( thread, 10000 ); CloseHandle( thread ); break; case 14: SetEvent( start_event ); Sleep( 200 ); PeekMessageA( &msg, HWND_TOPMOST, 0, 0, PM_NOREMOVE ); break; case 15: SetEvent( start_event ); Sleep( 200 ); PeekMessageA( &msg, HWND_BROADCAST, 0, 0, PM_NOREMOVE ); break; case 16: SetEvent( start_event ); Sleep( 200 ); PeekMessageA( &msg, HWND_BOTTOM, 0, 0, PM_NOREMOVE ); break; case 17: SetEvent( start_event ); Sleep( 200 ); PeekMessageA( &msg, (HWND)0xdeadbeef, 0, 0, PM_NOREMOVE ); break; case 18: SetEvent( start_event ); Sleep( 200 ); PeekMessageA( &msg, HWND_NOTOPMOST, 0, 0, PM_NOREMOVE ); break; case 19: SetEvent( start_event ); Sleep( 200 ); PeekMessageA( &msg, HWND_MESSAGE, 0, 0, PM_NOREMOVE ); break; case 20: SetEvent( start_event ); Sleep( 200 ); PeekMessageA( &msg, GetDesktopWindow(), 0, 0, PM_NOREMOVE ); break; } WaitForSingleObject( end_event, 2000 ); CloseHandle( start_event ); CloseHandle( end_event ); if (hwnd) DestroyWindow( hwnd );}
static LRESULT CALLBACK wait_idle_proc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ){ if (msg == WM_WININICHANGE) Sleep( 200 ); /* make sure the child waits */ return DefWindowProcA( hwnd, msg, wp, lp );}
static DWORD CALLBACK wait_idle_thread( void *arg ){ WNDCLASSA cls; MSG msg; HWND hwnd;
memset( &cls, 0, sizeof(cls) ); cls.lpfnWndProc = wait_idle_proc; cls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); cls.lpszClassName = "TestClass"; RegisterClassA( &cls );
hwnd = CreateWindowExA(0, "TestClass", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL); while (GetMessageA( &msg, 0, 0, 0 )) DispatchMessageA( &msg ); DestroyWindow(hwnd); return 0;}
static void test_WaitForInputIdle( char *argv0 ){ char path[MAX_PATH]; PROCESS_INFORMATION pi; STARTUPINFOA startup; BOOL ret; HANDLE start_event, end_event, thread; unsigned int i; DWORD id; const IMAGE_DOS_HEADER *dos = (const IMAGE_DOS_HEADER *)GetModuleHandleA(0); const IMAGE_NT_HEADERS *nt = (const IMAGE_NT_HEADERS *)((const char *)dos + dos->e_lfanew); BOOL console_app = (nt->OptionalHeader.Subsystem != IMAGE_SUBSYSTEM_WINDOWS_GUI);
if (console_app) /* build the test with -mwindows for better coverage */ trace( "not built as a GUI app, WaitForInputIdle may not be fully tested\n" );
start_event = CreateEventA(NULL, 0, 0, "test_WaitForInputIdle_start"); end_event = CreateEventA(NULL, 0, 0, "test_WaitForInputIdle_end"); ok(start_event != 0, "failed to create start event, error %u\n", GetLastError()); ok(end_event != 0, "failed to create end event, error %u\n", GetLastError());
memset( &startup, 0, sizeof(startup) ); startup.cb = sizeof(startup); startup.dwFlags = STARTF_USESHOWWINDOW; startup.wShowWindow = SW_SHOWNORMAL;
thread = CreateThread( NULL, 0, wait_idle_thread, NULL, 0, &id );
for (i = 0; i < ARRAY_SIZE(wait_idle_expect); i++) { ResetEvent( start_event ); ResetEvent( end_event );#ifdef __REACTOS__ sprintf( path, "%s msg_queue %u", argv0, i );#else sprintf( path, "%s msg %u", argv0, i );#endif ret = CreateProcessA( NULL, path, NULL, NULL, TRUE, 0, NULL, NULL, &startup, &pi ); ok( ret, "CreateProcess '%s' failed err %u.\n", path, GetLastError() ); if (ret) { ret = WaitForSingleObject( start_event, 5000 ); ok( ret == WAIT_OBJECT_0, "%u: WaitForSingleObject failed\n", i ); if (ret == WAIT_OBJECT_0) { ret = WaitForInputIdle( pi.hProcess, 1000 ); if (ret == WAIT_FAILED) ok( console_app || ret == wait_idle_expect[i].exp || broken(ret == wait_idle_expect[i].broken), "%u: WaitForInputIdle error %08x expected %08x\n", i, ret, wait_idle_expect[i].exp ); else todo_wine_if (wait_idle_expect[i].todo) ok( ret == wait_idle_expect[i].exp || broken(ret == wait_idle_expect[i].broken), "%u: WaitForInputIdle error %08x expected %08x\n", i, ret, wait_idle_expect[i].exp ); SetEvent( end_event ); WaitForSingleObject( pi.hProcess, 1000 ); /* give it a chance to exit on its own */ } TerminateProcess( pi.hProcess, 0 ); /* just in case */ winetest_wait_child_process( pi.hProcess ); ret = WaitForInputIdle( pi.hProcess, 100 ); ok( ret == WAIT_FAILED, "%u: WaitForInputIdle after exit error %08x\n", i, ret ); CloseHandle( pi.hProcess ); CloseHandle( pi.hThread ); } } CloseHandle( start_event ); PostThreadMessageA( id, WM_QUIT, 0, 0 ); WaitForSingleObject( thread, 10000 ); CloseHandle( thread );}
static const struct message WmSetParentSeq_1[] = { { WM_SHOWWINDOW, sent|wparam, 0 }, { EVENT_OBJECT_PARENTCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE }, { WM_CHILDACTIVATE, sent }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOREDRAW|SWP_NOCLIENTSIZE }, { WM_MOVE, sent|defwinproc|wparam, 0 }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SHOWWINDOW, sent|wparam, 1 }, { 0 }};
static const struct message WmSetParentSeq_2[] = { { WM_SHOWWINDOW, sent|wparam, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { HCBT_SETFOCUS, hook|optional }, { WM_NCACTIVATE, sent|wparam|optional, 0 }, { WM_ACTIVATE, sent|wparam|optional, 0 }, { WM_ACTIVATEAPP, sent|wparam|optional, 0 }, { WM_KILLFOCUS, sent|wparam, 0 }, { EVENT_OBJECT_PARENTCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE }, { HCBT_ACTIVATE, hook|optional }, { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, { WM_NCACTIVATE, sent|wparam|optional, 1 }, { WM_ACTIVATE, sent|wparam|optional, 1 }, { HCBT_SETFOCUS, hook|optional }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|optional|defwinproc }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOREDRAW|SWP_NOSIZE|SWP_NOCLIENTSIZE }, { WM_MOVE, sent|defwinproc|wparam, 0 }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SHOWWINDOW, sent|wparam, 1 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { 0 }};
static void test_SetParent(void){ HWND parent1, parent2, child, popup; RECT rc, rc_old;
parent1 = CreateWindowExA(0, "TestParentClass", NULL, WS_OVERLAPPEDWINDOW, 100, 100, 200, 200, 0, 0, 0, NULL); ok(parent1 != 0, "Failed to create parent1 window\n");
parent2 = CreateWindowExA(0, "TestParentClass", NULL, WS_OVERLAPPEDWINDOW, 400, 100, 200, 200, 0, 0, 0, NULL); ok(parent2 != 0, "Failed to create parent2 window\n");
/* WS_CHILD window */ child = CreateWindowExA(0, "TestWindowClass", NULL, WS_CHILD | WS_VISIBLE, 10, 10, 150, 150, parent1, 0, 0, NULL); ok(child != 0, "Failed to create child window\n");
GetWindowRect(parent1, &rc); trace("parent1 %s\n", wine_dbgstr_rect(&rc)); GetWindowRect(child, &rc_old); MapWindowPoints(0, parent1, (POINT *)&rc_old, 2); trace("child %s\n", wine_dbgstr_rect(&rc_old));
flush_sequence();
SetParent(child, parent2); flush_events(); ok_sequence(WmSetParentSeq_1, "SetParent() visible WS_CHILD", FALSE);
ok(GetWindowLongA(child, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); ok(!IsWindowVisible(child), "IsWindowVisible() should return FALSE\n");
GetWindowRect(parent2, &rc); trace("parent2 %s\n", wine_dbgstr_rect(&rc)); GetWindowRect(child, &rc); MapWindowPoints(0, parent2, (POINT *)&rc, 2); trace("child %s\n", wine_dbgstr_rect(&rc));
ok(EqualRect(&rc_old, &rc), "rects do not match %s / %s\n", wine_dbgstr_rect(&rc_old), wine_dbgstr_rect(&rc));
/* WS_POPUP window */ popup = CreateWindowExA(0, "TestWindowClass", NULL, WS_POPUP | WS_VISIBLE, 20, 20, 100, 100, 0, 0, 0, NULL); ok(popup != 0, "Failed to create popup window\n");
GetWindowRect(popup, &rc_old); trace("popup %s\n", wine_dbgstr_rect(&rc_old));
flush_sequence();
SetParent(popup, child); flush_events(); ok_sequence(WmSetParentSeq_2, "SetParent() visible WS_POPUP", TRUE);
ok(GetWindowLongA(popup, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); ok(!IsWindowVisible(popup), "IsWindowVisible() should return FALSE\n");
GetWindowRect(child, &rc); trace("parent2 %s\n", wine_dbgstr_rect(&rc)); GetWindowRect(popup, &rc); MapWindowPoints(0, child, (POINT *)&rc, 2); trace("popup %s\n", wine_dbgstr_rect(&rc));
ok(EqualRect(&rc_old, &rc), "rects do not match %s / %s\n", wine_dbgstr_rect(&rc_old), wine_dbgstr_rect(&rc));
DestroyWindow(popup); DestroyWindow(child); DestroyWindow(parent1); DestroyWindow(parent2);
flush_sequence();}
static const struct message WmKeyReleaseOnly[] = { { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 0x41, 0x80000001 }, { WM_KEYUP, sent|wparam|lparam, 0x41, 0x80000001 }, { 0 }};static const struct message WmKeyPressNormal[] = { { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 0x41, 0x1 }, { WM_KEYDOWN, sent|wparam|lparam, 0x41, 0x1 }, { 0 }};static const struct message WmKeyPressRepeat[] = { { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 0x41, 0x40000001 }, { WM_KEYDOWN, sent|wparam|lparam, 0x41, 0x40000001 }, { 0 }};static const struct message WmKeyReleaseNormal[] = { { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 0x41, 0xc0000001 }, { WM_KEYUP, sent|wparam|lparam, 0x41, 0xc0000001 }, { 0 }};
static void test_keyflags(void){ HWND test_window; SHORT key_state; BYTE keyboard_state[256]; MSG msg;
test_window = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 200, 200, 0, 0, 0, NULL);
flush_events(); flush_sequence();
/* keyup without a keydown */ keybd_event(0x41, 0, KEYEVENTF_KEYUP, 0); while (PeekMessageA(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(WmKeyReleaseOnly, "key release only", TRUE);
key_state = GetAsyncKeyState(0x41); ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state);
key_state = GetKeyState(0x41); ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state);
/* keydown */ keybd_event(0x41, 0, 0, 0); while (PeekMessageA(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(WmKeyPressNormal, "key press only", FALSE);
key_state = GetAsyncKeyState(0x41); ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state);
key_state = GetKeyState(0x41); ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state);
/* keydown repeat */ keybd_event(0x41, 0, 0, 0); while (PeekMessageA(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(WmKeyPressRepeat, "key press repeat", FALSE);
key_state = GetAsyncKeyState(0x41); ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state);
key_state = GetKeyState(0x41); ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state);
/* keyup */ keybd_event(0x41, 0, KEYEVENTF_KEYUP, 0); while (PeekMessageA(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(WmKeyReleaseNormal, "key release repeat", FALSE);
key_state = GetAsyncKeyState(0x41); ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state);
key_state = GetKeyState(0x41); ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state);
/* set the key state in this thread */ GetKeyboardState(keyboard_state); keyboard_state[0x41] = 0x80; SetKeyboardState(keyboard_state);
key_state = GetAsyncKeyState(0x41); ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state);
/* keydown */ keybd_event(0x41, 0, 0, 0); while (PeekMessageA(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(WmKeyPressRepeat, "key press after setkeyboardstate", TRUE);
key_state = GetAsyncKeyState(0x41); ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state);
key_state = GetKeyState(0x41); ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state);
/* clear the key state in this thread */ GetKeyboardState(keyboard_state); keyboard_state[0x41] = 0; SetKeyboardState(keyboard_state);
key_state = GetAsyncKeyState(0x41); ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state);
/* keyup */ keybd_event(0x41, 0, KEYEVENTF_KEYUP, 0); while (PeekMessageA(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(WmKeyReleaseOnly, "key release after setkeyboardstate", TRUE);
key_state = GetAsyncKeyState(0x41); ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state);
key_state = GetKeyState(0x41); ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state);
DestroyWindow(test_window); flush_sequence();}
static const struct message WmHotkeyPressLWIN[] = { { WM_KEYDOWN, kbd_hook|wparam|lparam, VK_LWIN, LLKHF_INJECTED }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_LWIN, 1 }, { WM_KEYDOWN, sent|wparam|lparam, VK_LWIN, 1 }, { 0 }};static const struct message WmHotkeyPress[] = { { WM_KEYDOWN, kbd_hook|lparam, 0, LLKHF_INJECTED }, { WM_HOTKEY, sent|wparam, 5 }, { 0 }};static const struct message WmHotkeyRelease[] = { { WM_KEYUP, kbd_hook|lparam, 0, LLKHF_INJECTED|LLKHF_UP }, { HCBT_KEYSKIPPED, hook|lparam|optional, 0, 0x80000001 }, { WM_KEYUP, sent|lparam, 0, 0x80000001 }, { 0 }};static const struct message WmHotkeyReleaseLWIN[] = { { WM_KEYUP, kbd_hook|wparam|lparam, VK_LWIN, LLKHF_INJECTED|LLKHF_UP }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_LWIN, 0xc0000001 }, { WM_KEYUP, sent|wparam|lparam, VK_LWIN, 0xc0000001 }, { 0 }};static const struct message WmHotkeyCombined[] = { { WM_KEYDOWN, kbd_hook|wparam|lparam, VK_LWIN, LLKHF_INJECTED }, { WM_KEYDOWN, kbd_hook|lparam, 0, LLKHF_INJECTED }, { WM_KEYUP, kbd_hook|lparam, 0, LLKHF_INJECTED|LLKHF_UP }, { WM_KEYUP, kbd_hook|wparam|lparam, VK_LWIN, LLKHF_INJECTED|LLKHF_UP }, { WM_APP, sent, 0, 0 }, { WM_HOTKEY, sent|wparam, 5 }, { WM_APP+1, sent, 0, 0 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_LWIN, 1 }, { WM_KEYDOWN, sent|wparam|lparam, VK_LWIN, 1 }, { HCBT_KEYSKIPPED, hook|optional, 0, 0x80000001 }, { WM_KEYUP, sent, 0, 0x80000001 }, /* lparam not checked so the sequence isn't a todo */ { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_LWIN, 0xc0000001 }, { WM_KEYUP, sent|wparam|lparam, VK_LWIN, 0xc0000001 }, { 0 }};static const struct message WmHotkeyPrevious[] = { { WM_KEYDOWN, kbd_hook|wparam|lparam, VK_LWIN, LLKHF_INJECTED }, { WM_KEYDOWN, kbd_hook|lparam, 0, LLKHF_INJECTED }, { WM_KEYUP, kbd_hook|lparam, 0, LLKHF_INJECTED|LLKHF_UP }, { WM_KEYUP, kbd_hook|wparam|lparam, VK_LWIN, LLKHF_INJECTED|LLKHF_UP }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_LWIN, 1 }, { WM_KEYDOWN, sent|wparam|lparam, VK_LWIN, 1 }, { HCBT_KEYSKIPPED, hook|lparam|optional, 0, 1 }, { WM_KEYDOWN, sent|lparam, 0, 1 }, { HCBT_KEYSKIPPED, hook|optional|lparam, 0, 0xc0000001 }, { WM_KEYUP, sent|lparam, 0, 0xc0000001 }, { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_LWIN, 0xc0000001 }, { WM_KEYUP, sent|wparam|lparam, VK_LWIN, 0xc0000001 }, { 0 }};static const struct message WmHotkeyNew[] = { { WM_KEYDOWN, kbd_hook|lparam, 0, LLKHF_INJECTED }, { WM_KEYUP, kbd_hook|lparam, 0, LLKHF_INJECTED|LLKHF_UP }, { WM_HOTKEY, sent|wparam, 5 }, { HCBT_KEYSKIPPED, hook|optional, 0, 0x80000001 }, { WM_KEYUP, sent, 0, 0x80000001 }, /* lparam not checked so the sequence isn't a todo */ { 0 }};
static int hotkey_letter;
static LRESULT CALLBACK KeyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam){ struct recvd_message msg;
if (nCode == HC_ACTION) { KBDLLHOOKSTRUCT *kdbhookstruct = (KBDLLHOOKSTRUCT*)lParam;
msg.hwnd = 0; msg.message = wParam; msg.flags = kbd_hook|wparam|lparam; msg.wParam = kdbhookstruct->vkCode; msg.lParam = kdbhookstruct->flags; msg.descr = "KeyboardHookProc"; add_message(&msg);
if (wParam == WM_KEYUP || wParam == WM_KEYDOWN) { ok(kdbhookstruct->vkCode == VK_LWIN || kdbhookstruct->vkCode == hotkey_letter, "unexpected keycode %x\n", kdbhookstruct->vkCode); } }
return CallNextHookEx(hKBD_hook, nCode, wParam, lParam);}
static void test_hotkey(void){ HWND test_window, taskbar_window; BOOL ret; MSG msg; DWORD queue_status; SHORT key_state;
SetLastError(0xdeadbeef); ret = UnregisterHotKey(NULL, 0); if (ret == TRUE) { skip("hotkeys not supported\n"); return; }
ok(ret == FALSE, "expected FALSE, got %i\n", ret); ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED || broken(GetLastError() == 0xdeadbeef), "unexpected error %d\n", GetLastError());
test_window = CreateWindowExA(0, "HotkeyWindowClass", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 200, 200, 0, 0, 0, NULL);
flush_sequence();
SetLastError(0xdeadbeef); ret = UnregisterHotKey(test_window, 0); ok(ret == FALSE, "expected FALSE, got %i\n", ret); ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED || broken(GetLastError() == 0xdeadbeef), "unexpected error %d\n", GetLastError());
/* Search for a Windows Key + letter combination that hasn't been registered */ for (hotkey_letter = 0x41; hotkey_letter <= 0x51; hotkey_letter ++) { SetLastError(0xdeadbeef); ret = RegisterHotKey(test_window, 5, MOD_WIN, hotkey_letter);
if (ret == TRUE) { break; } else { ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED || broken(GetLastError() == 0xdeadbeef), "unexpected error %d\n", GetLastError()); } }
if (hotkey_letter == 0x52) { ok(0, "Couldn't find any free Windows Key + letter combination\n"); goto end; }
hKBD_hook = SetWindowsHookExA(WH_KEYBOARD_LL, KeyboardHookProc, GetModuleHandleA(NULL), 0); if (!hKBD_hook) win_skip("WH_KEYBOARD_LL is not supported\n");
/* Same key combination, different id */ SetLastError(0xdeadbeef); ret = RegisterHotKey(test_window, 4, MOD_WIN, hotkey_letter); ok(ret == FALSE, "expected FALSE, got %i\n", ret); ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED || broken(GetLastError() == 0xdeadbeef), "unexpected error %d\n", GetLastError());
/* Same key combination, different window */ SetLastError(0xdeadbeef); ret = RegisterHotKey(NULL, 5, MOD_WIN, hotkey_letter); ok(ret == FALSE, "expected FALSE, got %i\n", ret); ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED || broken(GetLastError() == 0xdeadbeef), "unexpected error %d\n", GetLastError());
/* Register the same hotkey twice */ SetLastError(0xdeadbeef); ret = RegisterHotKey(test_window, 5, MOD_WIN, hotkey_letter); ok(ret == FALSE, "expected FALSE, got %i\n", ret); ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED || broken(GetLastError() == 0xdeadbeef), "unexpected error %d\n", GetLastError());
/* Window on another thread */ taskbar_window = FindWindowA("Shell_TrayWnd", NULL); if (!taskbar_window) { skip("no taskbar?\n"); } else { SetLastError(0xdeadbeef); ret = RegisterHotKey(taskbar_window, 5, 0, hotkey_letter); ok(ret == FALSE, "expected FALSE, got %i\n", ret); ok(GetLastError() == ERROR_WINDOW_OF_OTHER_THREAD || broken(GetLastError() == 0xdeadbeef), "unexpected error %d\n", GetLastError()); }
/* Inject the appropriate key sequence */ keybd_event(VK_LWIN, 0, 0, 0); while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(WmHotkeyPressLWIN, "window hotkey press LWIN", FALSE);
keybd_event(hotkey_letter, 0, 0, 0); queue_status = GetQueueStatus(QS_HOTKEY); ok((queue_status & (QS_HOTKEY << 16)) == QS_HOTKEY << 16, "expected QS_HOTKEY << 16 set, got %x\n", queue_status); while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) { if (msg.message == WM_HOTKEY) { ok(msg.hwnd == test_window, "unexpected hwnd %p\n", msg.hwnd); ok(msg.lParam == MAKELPARAM(MOD_WIN, hotkey_letter), "unexpected WM_HOTKEY lparam %lx\n", msg.lParam); } DispatchMessageA(&msg); } ok_sequence(WmHotkeyPress, "window hotkey press", FALSE);
queue_status = GetQueueStatus(QS_HOTKEY); ok((queue_status & (QS_HOTKEY << 16)) == 0, "expected QS_HOTKEY << 16 cleared, got %x\n", queue_status);
key_state = GetAsyncKeyState(hotkey_letter); ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state);
keybd_event(hotkey_letter, 0, KEYEVENTF_KEYUP, 0); while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(WmHotkeyRelease, "window hotkey release", TRUE);
keybd_event(VK_LWIN, 0, KEYEVENTF_KEYUP, 0); while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(WmHotkeyReleaseLWIN, "window hotkey release LWIN", FALSE);
/* normal posted WM_HOTKEY messages set QS_HOTKEY */ PostMessageA(test_window, WM_HOTKEY, 0, 0); queue_status = GetQueueStatus(QS_HOTKEY); ok((queue_status & (QS_HOTKEY << 16)) == QS_HOTKEY << 16, "expected QS_HOTKEY << 16 set, got %x\n", queue_status); queue_status = GetQueueStatus(QS_POSTMESSAGE); ok((queue_status & (QS_POSTMESSAGE << 16)) == QS_POSTMESSAGE << 16, "expected QS_POSTMESSAGE << 16 set, got %x\n", queue_status); while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); flush_sequence();
/* Send and process all messages at once */ PostMessageA(test_window, WM_APP, 0, 0); keybd_event(VK_LWIN, 0, 0, 0); keybd_event(hotkey_letter, 0, 0, 0); keybd_event(hotkey_letter, 0, KEYEVENTF_KEYUP, 0); keybd_event(VK_LWIN, 0, KEYEVENTF_KEYUP, 0);
while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) { if (msg.message == WM_HOTKEY) { ok(msg.hwnd == test_window, "unexpected hwnd %p\n", msg.hwnd); ok(msg.lParam == MAKELPARAM(MOD_WIN, hotkey_letter), "unexpected WM_HOTKEY lparam %lx\n", msg.lParam); } DispatchMessageA(&msg); } ok_sequence(WmHotkeyCombined, "window hotkey combined", FALSE);
/* Register same hwnd/id with different key combination */ ret = RegisterHotKey(test_window, 5, 0, hotkey_letter); ok(ret == TRUE, "expected TRUE, got %i, err=%d\n", ret, GetLastError());
/* Previous key combination does not work */ keybd_event(VK_LWIN, 0, 0, 0); keybd_event(hotkey_letter, 0, 0, 0); keybd_event(hotkey_letter, 0, KEYEVENTF_KEYUP, 0); keybd_event(VK_LWIN, 0, KEYEVENTF_KEYUP, 0);
while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(WmHotkeyPrevious, "window hotkey previous", FALSE);
/* New key combination works */ keybd_event(hotkey_letter, 0, 0, 0); keybd_event(hotkey_letter, 0, KEYEVENTF_KEYUP, 0);
while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) { if (msg.message == WM_HOTKEY) { ok(msg.hwnd == test_window, "unexpected hwnd %p\n", msg.hwnd); ok(msg.lParam == MAKELPARAM(0, hotkey_letter), "unexpected WM_HOTKEY lparam %lx\n", msg.lParam); } DispatchMessageA(&msg); } ok_sequence(WmHotkeyNew, "window hotkey new", FALSE);
/* Unregister hotkey properly */ ret = UnregisterHotKey(test_window, 5); ok(ret == TRUE, "expected TRUE, got %i, err=%d\n", ret, GetLastError());
/* Unregister hotkey again */ SetLastError(0xdeadbeef); ret = UnregisterHotKey(test_window, 5); ok(ret == FALSE, "expected FALSE, got %i\n", ret); ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED || broken(GetLastError() == 0xdeadbeef), "unexpected error %d\n", GetLastError());
/* Register thread hotkey */ ret = RegisterHotKey(NULL, 5, MOD_WIN, hotkey_letter); ok(ret == TRUE, "expected TRUE, got %i, err=%d\n", ret, GetLastError());
/* Inject the appropriate key sequence */ keybd_event(VK_LWIN, 0, 0, 0); while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) { ok(msg.hwnd != NULL, "unexpected thread message %x\n", msg.message); DispatchMessageA(&msg); } ok_sequence(WmHotkeyPressLWIN, "thread hotkey press LWIN", FALSE);
keybd_event(hotkey_letter, 0, 0, 0); while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) { if (msg.message == WM_HOTKEY) { struct recvd_message message; ok(msg.hwnd == NULL, "unexpected hwnd %p\n", msg.hwnd); ok(msg.lParam == MAKELPARAM(MOD_WIN, hotkey_letter), "unexpected WM_HOTKEY lparam %lx\n", msg.lParam); message.message = msg.message; message.flags = sent|wparam|lparam; message.wParam = msg.wParam; message.lParam = msg.lParam; message.descr = "test_hotkey thread message"; add_message(&message); } else ok(msg.hwnd != NULL, "unexpected thread message %x\n", msg.message); DispatchMessageA(&msg); } ok_sequence(WmHotkeyPress, "thread hotkey press", FALSE);
keybd_event(hotkey_letter, 0, KEYEVENTF_KEYUP, 0); while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) { ok(msg.hwnd != NULL, "unexpected thread message %x\n", msg.message); DispatchMessageA(&msg); } ok_sequence(WmHotkeyRelease, "thread hotkey release", TRUE);
keybd_event(VK_LWIN, 0, KEYEVENTF_KEYUP, 0); while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) { ros_skip_flaky ok(msg.hwnd != NULL, "unexpected thread message %x\n", msg.message); DispatchMessageA(&msg); } ok_sequence(WmHotkeyReleaseLWIN, "thread hotkey release LWIN", FALSE);
/* Unregister thread hotkey */ ret = UnregisterHotKey(NULL, 5); ok(ret == TRUE, "expected TRUE, got %i, err=%d\n", ret, GetLastError());
if (hKBD_hook) UnhookWindowsHookEx(hKBD_hook); hKBD_hook = NULL;
end: UnregisterHotKey(NULL, 5); UnregisterHotKey(test_window, 5); DestroyWindow(test_window); flush_sequence();}
static const struct message WmSetFocus_1[] = { { HCBT_SETFOCUS, hook }, /* child */ { HCBT_ACTIVATE, hook }, /* parent */ { WM_QUERYNEWPALETTE, sent|wparam|lparam|parent|optional, 0, 0 }, { WM_WINDOWPOSCHANGING, sent|parent, 0, SWP_NOSIZE|SWP_NOMOVE }, { WM_ACTIVATEAPP, sent|wparam|parent, 1 }, { WM_NCACTIVATE, sent|parent }, { WM_GETTEXT, sent|defwinproc|parent|optional }, { WM_GETTEXT, sent|defwinproc|parent|optional }, { WM_ACTIVATE, sent|wparam|parent, 1 }, { HCBT_SETFOCUS, hook }, /* parent */ { WM_SETFOCUS, sent|defwinproc|parent }, { WM_KILLFOCUS, sent|parent }, { WM_SETFOCUS, sent }, { 0 }};static const struct message WmSetFocus_2[] = { { HCBT_SETFOCUS, hook }, /* parent */ { WM_KILLFOCUS, sent }, { WM_SETFOCUS, sent|parent }, { 0 }};static const struct message WmSetFocus_3[] = { { HCBT_SETFOCUS, hook }, /* child */ { 0 }};
static void test_SetFocus(void){ HWND parent, old_parent, child, old_focus, old_active; MSG msg; struct wnd_event wnd_event; HANDLE hthread; DWORD ret, tid;
wnd_event.start_event = CreateEventW(NULL, 0, 0, NULL); ok(wnd_event.start_event != 0, "CreateEvent error %d\n", GetLastError()); hthread = CreateThread(NULL, 0, thread_proc, &wnd_event, 0, &tid); ok(hthread != 0, "CreateThread error %d\n", GetLastError()); ret = WaitForSingleObject(wnd_event.start_event, INFINITE); ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); CloseHandle(wnd_event.start_event);
parent = CreateWindowExA(0, "TestParentClass", NULL, WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, 0, 0, 0, NULL); ok(parent != 0, "failed to create parent window\n"); child = CreateWindowExA(0, "TestWindowClass", NULL, WS_CHILD, 0, 0, 0, 0, parent, 0, 0, NULL); ok(child != 0, "failed to create child window\n");
trace("parent %p, child %p, thread window %p\n", parent, child, wnd_event.hwnd);
SetFocus(0); SetActiveWindow(0);
flush_events(); flush_sequence();
ok(GetActiveWindow() == 0, "expected active 0, got %p\n", GetActiveWindow()); ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
log_all_parent_messages++;
old_focus = SetFocus(child); while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(WmSetFocus_1, "SetFocus on a child window", TRUE); ok(old_focus == parent, "expected old focus %p, got %p\n", parent, old_focus); ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); ok(GetFocus() == child, "expected focus %p, got %p\n", child, GetFocus());
old_focus = SetFocus(parent); while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(WmSetFocus_2, "SetFocus on a parent window", FALSE); ok(old_focus == child, "expected old focus %p, got %p\n", child, old_focus); ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus());
SetLastError(0xdeadbeef); old_focus = SetFocus((HWND)0xdeadbeef); ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || broken(GetLastError() == 0xdeadbeef), "expected ERROR_INVALID_WINDOW_HANDLE, got %d\n", GetLastError()); while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(WmEmptySeq, "SetFocus on an invalid window", FALSE); ok(old_focus == 0, "expected old focus 0, got %p\n", old_focus); ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus());
SetLastError(0xdeadbeef); old_focus = SetFocus(GetDesktopWindow()); ok(GetLastError() == ERROR_ACCESS_DENIED /* Vista+ */ || broken(GetLastError() == 0xdeadbeef), "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError()); while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(WmEmptySeq, "SetFocus on a desktop window", TRUE); ok(old_focus == 0, "expected old focus 0, got %p\n", old_focus); ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus());
SetLastError(0xdeadbeef); old_focus = SetFocus(wnd_event.hwnd); ok(GetLastError() == ERROR_ACCESS_DENIED /* Vista+ */ || broken(GetLastError() == 0xdeadbeef), "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError()); while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(WmEmptySeq, "SetFocus on another thread window", TRUE); ok(old_focus == 0, "expected old focus 0, got %p\n", old_focus); ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus());
SetLastError(0xdeadbeef); old_active = SetActiveWindow((HWND)0xdeadbeef); ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || broken(GetLastError() == 0xdeadbeef), "expected ERROR_INVALID_WINDOW_HANDLE, got %d\n", GetLastError()); while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(WmEmptySeq, "SetActiveWindow on an invalid window", FALSE); ok(old_active == 0, "expected old focus 0, got %p\n", old_active); ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus());
SetLastError(0xdeadbeef); old_active = SetActiveWindow(GetDesktopWindow());todo_wine ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError()); while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(WmEmptySeq, "SetActiveWindow on a desktop window", TRUE); ok(old_active == 0, "expected old focus 0, got %p\n", old_focus); ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus());
SetLastError(0xdeadbeef); old_active = SetActiveWindow(wnd_event.hwnd);todo_wine ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError()); while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(WmEmptySeq, "SetActiveWindow on another thread window", TRUE); ok(old_active == 0, "expected old focus 0, got %p\n", old_active); ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus());
SetLastError(0xdeadbeef); ret = AttachThreadInput(GetCurrentThreadId(), tid, TRUE); ok(ret, "AttachThreadInput error %d\n", GetLastError());
ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus());
flush_events(); flush_sequence();
old_focus = SetFocus(wnd_event.hwnd); while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok(old_focus == wnd_event.hwnd, "expected old focus %p, got %p\n", wnd_event.hwnd, old_focus); ok(GetActiveWindow() == wnd_event.hwnd, "expected active %p, got %p\n", wnd_event.hwnd, GetActiveWindow()); ok(GetFocus() == wnd_event.hwnd, "expected focus %p, got %p\n", wnd_event.hwnd, GetFocus());
old_focus = SetFocus(parent); while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok(old_focus == parent, "expected old focus %p, got %p\n", parent, old_focus); ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus());
flush_events(); flush_sequence();
old_active = SetActiveWindow(wnd_event.hwnd); while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok(old_active == parent, "expected old focus %p, got %p\n", parent, old_active); ok(GetActiveWindow() == wnd_event.hwnd, "expected active %p, got %p\n", wnd_event.hwnd, GetActiveWindow()); ok(GetFocus() == wnd_event.hwnd, "expected focus %p, got %p\n", wnd_event.hwnd, GetFocus());
SetLastError(0xdeadbeef); ret = AttachThreadInput(GetCurrentThreadId(), tid, FALSE); ok(ret, "AttachThreadInput error %d\n", GetLastError());
ok(GetActiveWindow() == 0, "expected active 0, got %p\n", GetActiveWindow()); ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
old_parent = SetParent(child, GetDesktopWindow()); ok(old_parent == parent, "expected old parent %p, got %p\n", parent, old_parent);
ok(GetActiveWindow() == 0, "expected active 0, got %p\n", GetActiveWindow()); ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
old_focus = SetFocus(parent); while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok(old_focus == parent, "expected old focus %p, got %p\n", parent, old_focus); ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus());
flush_events(); flush_sequence();
SetLastError(0xdeadbeef); old_focus = SetFocus(child);todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER /* Vista+ */ || broken(GetLastError() == 0) /* XP */ || broken(GetLastError() == 0xdeadbeef), "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(WmSetFocus_3, "SetFocus on a child window", TRUE); ok(old_focus == 0, "expected old focus 0, got %p\n", old_focus); ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus());
SetLastError(0xdeadbeef); old_active = SetActiveWindow(child); ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError()); while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(WmEmptySeq, "SetActiveWindow on a child window", FALSE); ok(old_active == parent, "expected old active %p, got %p\n", parent, old_active); ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus());
log_all_parent_messages--;
DestroyWindow(child); DestroyWindow(parent);
ret = PostMessageA(wnd_event.hwnd, WM_QUIT, 0, 0); ok(ret, "PostMessage(WM_QUIT) error %d\n", GetLastError()); ret = WaitForSingleObject(hthread, INFINITE); ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); CloseHandle(hthread);}
static const struct message WmSetLayeredStyle[] = { { WM_STYLECHANGING, sent }, { WM_STYLECHANGED, sent }, { WM_GETTEXT, sent|defwinproc|optional }, { 0 }};
static const struct message WmSetLayeredStyle2[] = { { WM_STYLECHANGING, sent }, { WM_STYLECHANGED, sent }, { WM_WINDOWPOSCHANGING, sent|optional|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { WM_NCCALCSIZE, sent|optional|wparam|defwinproc, 1 }, { WM_WINDOWPOSCHANGED, sent|optional|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { WM_MOVE, sent|optional|defwinproc|wparam, 0 }, { WM_SIZE, sent|optional|defwinproc|wparam, SIZE_RESTORED }, { 0 }};
struct layered_window_info{ HWND hwnd; HDC hdc; SIZE size; HANDLE event; BOOL ret;};
static DWORD CALLBACK update_layered_proc( void *param ){ struct layered_window_info *info = param; POINT src = { 0, 0 };
info->ret = pUpdateLayeredWindow( info->hwnd, 0, NULL, &info->size, info->hdc, &src, 0, NULL, ULW_OPAQUE ); ok( info->ret, "failed\n"); SetEvent( info->event ); return 0;}
static void test_layered_window(void){ HWND hwnd; HDC hdc; HBITMAP bmp; BOOL ret; SIZE size; POINT pos, src; RECT rect, client; HANDLE thread; DWORD tid; struct layered_window_info info;
if (!pUpdateLayeredWindow) { win_skip( "UpdateLayeredWindow not supported\n" ); return; }
hdc = CreateCompatibleDC( 0 ); bmp = CreateCompatibleBitmap( hdc, 300, 300 ); SelectObject( hdc, bmp );
hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_CAPTION | WS_THICKFRAME | WS_SYSMENU, 100, 100, 300, 300, 0, 0, 0, NULL); ok( hwnd != 0, "failed to create window\n" ); ShowWindow( hwnd, SW_SHOWNORMAL ); UpdateWindow( hwnd ); flush_events(); flush_sequence();
GetWindowRect( hwnd, &rect ); GetClientRect( hwnd, &client ); ok( client.right < rect.right - rect.left, "wrong client area\n" ); ok( client.bottom < rect.bottom - rect.top, "wrong client area\n" );
src.x = src.y = 0; pos.x = pos.y = 300; size.cx = size.cy = 250; ret = pUpdateLayeredWindow( hwnd, 0, &pos, &size, hdc, &src, 0, NULL, ULW_OPAQUE ); ok( !ret, "UpdateLayeredWindow should fail on non-layered window\n" ); ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() ); SetWindowLongA( hwnd, GWL_EXSTYLE, GetWindowLongA(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED ); ok_sequence( WmSetLayeredStyle, "WmSetLayeredStyle", FALSE );
ret = pUpdateLayeredWindow( hwnd, 0, &pos, &size, hdc, &src, 0, NULL, ULW_OPAQUE ); ok( ret, "UpdateLayeredWindow failed err %u\n", GetLastError() ); ok_sequence( WmEmptySeq, "UpdateLayeredWindow", FALSE ); GetWindowRect( hwnd, &rect ); ok( rect.left == 300 && rect.top == 300 && rect.right == 550 && rect.bottom == 550, "wrong window rect %s\n", wine_dbgstr_rect( &rect )); GetClientRect( hwnd, &rect ); ok( rect.right == client.right - 50 && rect.bottom == client.bottom - 50, "wrong client rect %s\n", wine_dbgstr_rect( &rect ));
size.cx = 150; pos.y = 200; ret = pUpdateLayeredWindow( hwnd, 0, &pos, &size, hdc, &src, 0, NULL, ULW_OPAQUE ); ok( ret, "UpdateLayeredWindow failed err %u\n", GetLastError() ); ok_sequence( WmEmptySeq, "UpdateLayeredWindow", FALSE ); GetWindowRect( hwnd, &rect ); ok( rect.left == 300 && rect.top == 200 && rect.right == 450 && rect.bottom == 450, "wrong window rect %s\n", wine_dbgstr_rect( &rect )); GetClientRect( hwnd, &rect ); ok( rect.right == client.right - 150 && rect.bottom == client.bottom - 50, "wrong client rect %s\n", wine_dbgstr_rect( &rect ));
SetWindowLongA( hwnd, GWL_STYLE, GetWindowLongA(hwnd, GWL_STYLE) & ~(WS_CAPTION | WS_THICKFRAME | WS_SYSMENU) ); ok_sequence( WmSetLayeredStyle2, "WmSetLayeredStyle2", FALSE );
size.cx = 200; pos.x = 200; ret = pUpdateLayeredWindow( hwnd, 0, &pos, &size, hdc, &src, 0, NULL, ULW_OPAQUE ); ok( ret, "UpdateLayeredWindow failed err %u\n", GetLastError() ); ok_sequence( WmEmptySeq, "UpdateLayeredWindow", FALSE ); GetWindowRect( hwnd, &rect ); ok( rect.left == 200 && rect.top == 200 && rect.right == 400 && rect.bottom == 450, "wrong window rect %s\n", wine_dbgstr_rect( &rect )); GetClientRect( hwnd, &rect ); ok( (rect.right == 200 && rect.bottom == 250) || broken(rect.right == client.right - 100 && rect.bottom == client.bottom - 50), "wrong client rect %s\n", wine_dbgstr_rect( &rect ));
size.cx = 0; ret = pUpdateLayeredWindow( hwnd, 0, &pos, &size, hdc, &src, 0, NULL, ULW_OPAQUE ); ok( !ret, "UpdateLayeredWindow should fail on non-layered window\n" ); ok( GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == ERROR_MR_MID_NOT_FOUND) || broken(GetLastError() == ERROR_GEN_FAILURE) /* win7 */, "wrong error %u\n", GetLastError() ); size.cx = 1; size.cy = -1; ret = pUpdateLayeredWindow( hwnd, 0, &pos, &size, hdc, &src, 0, NULL, ULW_OPAQUE ); ok( !ret, "UpdateLayeredWindow should fail on non-layered window\n" ); ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
SetWindowLongA( hwnd, GWL_EXSTYLE, GetWindowLongA(hwnd, GWL_EXSTYLE) & ~WS_EX_LAYERED ); ok_sequence( WmSetLayeredStyle, "WmSetLayeredStyle", FALSE ); GetWindowRect( hwnd, &rect ); ok( rect.left == 200 && rect.top == 200 && rect.right == 400 && rect.bottom == 450, "wrong window rect %s\n", wine_dbgstr_rect( &rect )); GetClientRect( hwnd, &rect ); ok( (rect.right == 200 && rect.bottom == 250) || broken(rect.right == client.right - 100 && rect.bottom == client.bottom - 50), "wrong client rect %s\n", wine_dbgstr_rect( &rect ));
SetWindowLongA( hwnd, GWL_EXSTYLE, GetWindowLongA(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED ); info.hwnd = hwnd; info.hdc = hdc; info.size.cx = 250; info.size.cy = 300; info.event = CreateEventA( NULL, TRUE, FALSE, NULL ); info.ret = FALSE; thread = CreateThread( NULL, 0, update_layered_proc, &info, 0, &tid ); ok( WaitForSingleObject( info.event, 1000 ) == 0, "wait failed\n" ); ok( info.ret, "UpdateLayeredWindow failed in other thread\n" ); WaitForSingleObject( thread, 1000 ); CloseHandle( thread ); GetWindowRect( hwnd, &rect ); ok( rect.left == 200 && rect.top == 200 && rect.right == 450 && rect.bottom == 500, "wrong window rect %s\n", wine_dbgstr_rect( &rect )); GetClientRect( hwnd, &rect ); ok( (rect.right == 250 && rect.bottom == 300) || broken(rect.right == client.right - 50 && rect.bottom == client.bottom), "wrong client rect %s\n", wine_dbgstr_rect( &rect ));
DestroyWindow( hwnd ); DeleteDC( hdc ); DeleteObject( bmp );}
static HMENU hpopupmenu;
static LRESULT WINAPI cancel_popup_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ if (ignore_message( message )) return 0;
switch (message) { case WM_ENTERIDLE: todo_wine ok(GetCapture() == hwnd, "expected %p, got %p\n", hwnd, GetCapture()); EndMenu(); break; case WM_INITMENU: case WM_INITMENUPOPUP: case WM_UNINITMENUPOPUP: ok((HMENU)wParam == hpopupmenu, "expected %p, got %lx\n", hpopupmenu, wParam); break; case WM_CAPTURECHANGED: todo_wine ok(!lParam || (HWND)lParam == hwnd, "lost capture to %lx\n", lParam); break; }
return MsgCheckProc (FALSE, hwnd, message, wParam, lParam);}
static LRESULT WINAPI cancel_init_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ if (ignore_message( message )) return 0;
switch (message) { case WM_ENTERMENULOOP: ok(EndMenu() == TRUE, "EndMenu() failed\n"); break; }
return MsgCheckProc (FALSE, hwnd, message, wParam, lParam);}
static void test_TrackPopupMenu(void){ MSG msg; HWND hwnd; BOOL ret;
hwnd = CreateWindowExA(0, "TestWindowClass", NULL, 0, 0, 0, 1, 1, 0, NULL, NULL, 0); ok(hwnd != NULL, "CreateWindowEx failed with error %d\n", GetLastError());
SetWindowLongPtrA( hwnd, GWLP_WNDPROC, (LONG_PTR)cancel_popup_proc);
hpopupmenu = CreatePopupMenu(); ok(hpopupmenu != NULL, "CreateMenu failed with error %d\n", GetLastError());
AppendMenuA(hpopupmenu, MF_STRING, 100, "item 1"); AppendMenuA(hpopupmenu, MF_STRING, 100, "item 2");
flush_events(); flush_sequence(); ret = TrackPopupMenu(hpopupmenu, 0, 100,100, 0, hwnd, NULL); ok_sequence(WmTrackPopupMenu, "TrackPopupMenu", TRUE); ok(ret == 1, "TrackPopupMenu failed with error %i\n", GetLastError());
/* Test popup closing with an ESC-press */ flush_events(); PostMessageW(hwnd, WM_KEYDOWN, VK_ESCAPE, 0); ret = TrackPopupMenu(hpopupmenu, 0, 100,100, 0, hwnd, NULL); ok(ret == 1, "TrackPopupMenu failed with error %i\n", GetLastError()); PostQuitMessage(0); flush_sequence(); while ( PeekMessageA(&msg, 0, 0, 0, PM_REMOVE) ) { TranslateMessage(&msg); DispatchMessageA(&msg); } ok_sequence(WmTrackPopupMenuEsc, "TrackPopupMenuEsc", FALSE); /* Shouldn't get any message */
SetWindowLongPtrA( hwnd, GWLP_WNDPROC, (LONG_PTR)cancel_init_proc);
flush_events(); flush_sequence(); ret = TrackPopupMenu(hpopupmenu, 0, 100,100, 0, hwnd, NULL); ok_sequence(WmTrackPopupMenuAbort, "WmTrackPopupMenuAbort", TRUE); ok(ret == TRUE, "TrackPopupMenu failed\n");
SetWindowLongPtrA( hwnd, GWLP_WNDPROC, (LONG_PTR)cancel_popup_proc);
SetCapture(hwnd);
flush_events(); flush_sequence(); ret = TrackPopupMenu(hpopupmenu, 0, 100,100, 0, hwnd, NULL); ok_sequence(WmTrackPopupMenuCapture, "TrackPopupMenuCapture", TRUE); ok(ret == 1, "TrackPopupMenuCapture failed with error %i\n", GetLastError());
DestroyMenu(hpopupmenu); DestroyWindow(hwnd);}
static void test_TrackPopupMenuEmpty(void){ HWND hwnd; BOOL ret;
hwnd = CreateWindowExA(0, "TestWindowClass", NULL, 0, 0, 0, 1, 1, 0, NULL, NULL, 0); ok(hwnd != NULL, "CreateWindowEx failed with error %d\n", GetLastError());
SetWindowLongPtrA( hwnd, GWLP_WNDPROC, (LONG_PTR)cancel_popup_proc);
hpopupmenu = CreatePopupMenu(); ok(hpopupmenu != NULL, "CreateMenu failed with error %d\n", GetLastError());
flush_events(); flush_sequence(); ret = TrackPopupMenu(hpopupmenu, 0, 100,100, 0, hwnd, NULL); ok_sequence(WmTrackPopupMenuEmpty, "TrackPopupMenuEmpty", TRUE); ok(ret == 0, "TrackPopupMenu succeeded\n");
DestroyMenu(hpopupmenu); DestroyWindow(hwnd);}
static const struct message send_message_1[] = { { WM_USER+2, sent|wparam|lparam, 0, 0 }, { WM_USER, sent|wparam|lparam, 0, 0 }, { 0 }};static const struct message send_message_2[] = { { WM_USER+4, sent|wparam|lparam, 0, 0 }, { 0 }};static const struct message send_message_3[] = { { WM_USER+3, sent|wparam|lparam, 0, 0 }, { WM_USER+1, sent|wparam|lparam, 0, 0 }, { 0 }};
static DWORD WINAPI SendMessage_thread_1(void *param){ struct wnd_event *wnd_event = param;
trace("thread: starting\n"); WaitForSingleObject(wnd_event->start_event, INFINITE);
trace("thread: call PostMessage\n"); PostMessageA(wnd_event->hwnd, WM_USER, 0, 0);
trace("thread: call PostMessage\n"); PostMessageA(wnd_event->hwnd, WM_USER+1, 0, 0);
trace("thread: call SendMessage\n"); SendMessageA(wnd_event->hwnd, WM_USER+2, 0, 0);
trace("thread: call SendMessage\n"); SendMessageA(wnd_event->hwnd, WM_USER+3, 0, 0);
return 0;}
static DWORD WINAPI SendMessage_thread_2(void *param){ struct wnd_event *wnd_event = param;
trace("thread: starting\n"); WaitForSingleObject(wnd_event->start_event, INFINITE);
trace("thread: call PostMessage\n"); PostMessageA(wnd_event->hwnd, WM_USER, 0, 0);
trace("thread: call PostMessage\n"); PostMessageA(wnd_event->hwnd, WM_USER+1, 0, 0);
/* this leads to sending an internal message under Wine */ trace("thread: call SetParent\n"); SetParent(wnd_event->hwnd, wnd_event->hwnd);
trace("thread: call SendMessage\n"); SendMessageA(wnd_event->hwnd, WM_USER+2, 0, 0);
trace("thread: call SendMessage\n"); SendMessageA(wnd_event->hwnd, WM_USER+3, 0, 0);
return 0;}
static void test_SendMessage_other_thread(int thread_n){ DWORD qs_all_input = QS_ALLINPUT & ~QS_RAWINPUT; HANDLE hthread; struct wnd_event wnd_event; DWORD tid, ret; MSG msg;
wnd_event.start_event = CreateEventA(NULL, 0, 0, NULL);
wnd_event.hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW, 100, 100, 200, 200, 0, 0, 0, NULL); ok(wnd_event.hwnd != 0, "CreateWindowEx failed\n");
hthread = CreateThread(NULL, 0, thread_n == 1 ? SendMessage_thread_1 : SendMessage_thread_2, &wnd_event, 0, &tid); ok(hthread != NULL, "CreateThread failed, error %d\n", GetLastError()); CloseHandle(hthread);
flush_events(); flush_sequence();
ret = GetQueueStatus(QS_SENDMESSAGE); ok(ret == 0, "wrong status %08x\n", ret);
SetEvent(wnd_event.start_event);
/* wait for other thread's SendMessage */ for (;;) { ret = GetQueueStatus(QS_SENDMESSAGE); if (ret == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE)) break; Sleep(50); }
ret = GetQueueStatus(QS_SENDMESSAGE|QS_POSTMESSAGE); ok(ret == MAKELONG(QS_POSTMESSAGE, QS_SENDMESSAGE|QS_POSTMESSAGE), "wrong status %08x\n", ret);
trace("main: call GetMessage\n"); GetMessageA(&msg, 0, 0, 0); ok(msg.message == WM_USER, "expected WM_USER, got %04x\n", msg.message); DispatchMessageA(&msg); ok_sequence(send_message_1, "SendMessage from other thread 1", thread_n == 2);
/* intentionally yield */ MsgWaitForMultipleObjects(0, NULL, FALSE, 100, qs_all_input);
trace("main: call SendMessage\n"); SendMessageA(wnd_event.hwnd, WM_USER+4, 0, 0); ok_sequence(send_message_2, "SendMessage from other thread 2", FALSE);
ret = GetQueueStatus(QS_SENDMESSAGE|QS_POSTMESSAGE); ok(ret == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_POSTMESSAGE), "wrong status %08x\n", ret);
trace("main: call PeekMessage\n"); ok(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "PeekMessage should not fail\n"); ok(msg.message == WM_USER+1, "expected WM_USER+1, got %04x\n", msg.message); DispatchMessageA(&msg); ok_sequence(send_message_3, "SendMessage from other thread 3", thread_n == 2);
/* intentionally yield */ MsgWaitForMultipleObjects(0, NULL, FALSE, 100, qs_all_input);
ret = GetQueueStatus(QS_SENDMESSAGE|QS_POSTMESSAGE); /* FIXME: remove once Wine is fixed */todo_wine_if (thread_n == 2) ok(ret == 0, "wrong status %08x\n", ret);
trace("main: call PeekMessage\n"); ok(!PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "PeekMessage should fail\n"); ok_sequence(WmEmptySeq, "SendMessage from other thread 5", thread_n == 2);
ret = GetQueueStatus(QS_SENDMESSAGE|QS_POSTMESSAGE); ok(ret == 0, "wrong status %08x\n", ret);
trace("main: call DestroyWindow\n"); DestroyWindow(msg.hwnd);
flush_events(); flush_sequence();}
static LRESULT CALLBACK insendmessage_wnd_proc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ){ DWORD flags = InSendMessageEx( NULL ); BOOL ret;
switch (msg) { case WM_USER: ok( flags == ISMEX_SEND, "wrong flags %x\n", flags ); ok( InSendMessage(), "InSendMessage returned false\n" ); ret = ReplyMessage( msg ); ok( ret, "ReplyMessage failed err %u\n", GetLastError() ); flags = InSendMessageEx( NULL ); ok( flags == (ISMEX_SEND | ISMEX_REPLIED), "wrong flags %x\n", flags ); ok( InSendMessage(), "InSendMessage returned false\n" ); break; case WM_USER + 1: ok( flags == ISMEX_NOTIFY, "wrong flags %x\n", flags ); ok( InSendMessage(), "InSendMessage returned false\n" ); ret = ReplyMessage( msg ); ok( ret, "ReplyMessage failed err %u\n", GetLastError() ); flags = InSendMessageEx( NULL ); ok( flags == ISMEX_NOTIFY, "wrong flags %x\n", flags ); ok( InSendMessage(), "InSendMessage returned false\n" ); break; case WM_USER + 2: ok( flags == ISMEX_CALLBACK, "wrong flags %x\n", flags ); ok( InSendMessage(), "InSendMessage returned false\n" ); ret = ReplyMessage( msg ); ok( ret, "ReplyMessage failed err %u\n", GetLastError() ); flags = InSendMessageEx( NULL ); ok( flags == (ISMEX_CALLBACK | ISMEX_REPLIED) || flags == ISMEX_SEND, "wrong flags %x\n", flags ); ok( InSendMessage(), "InSendMessage returned false\n" ); break; case WM_USER + 3: ok( flags == ISMEX_NOSEND, "wrong flags %x\n", flags ); ok( !InSendMessage(), "InSendMessage returned true\n" ); ret = ReplyMessage( msg ); ok( !ret, "ReplyMessage succeeded\n" ); break; }
return DefWindowProcA( hwnd, msg, wp, lp );}
static void CALLBACK msg_callback( HWND hwnd, UINT msg, ULONG_PTR arg, LRESULT result ){ ok( msg == WM_USER + 2, "wrong msg %x\n", msg ); ok( result == WM_USER + 2, "wrong result %lx\n", result );}
static DWORD WINAPI send_message_thread( void *arg ){ HWND win = arg;
SendMessageA( win, WM_USER, 0, 0 ); SendNotifyMessageA( win, WM_USER + 1, 0, 0 ); SendMessageCallbackA( win, WM_USER + 2, 0, 0, msg_callback, 0 ); PostMessageA( win, WM_USER + 3, 0, 0 ); PostMessageA( win, WM_QUIT, 0, 0 ); return 0;}
static void test_InSendMessage(void){ WNDCLASSA cls; HWND win; MSG msg; HANDLE thread; DWORD tid;
memset(&cls, 0, sizeof(cls)); cls.lpfnWndProc = insendmessage_wnd_proc; cls.hInstance = GetModuleHandleA(NULL); cls.lpszClassName = "InSendMessage_test"; RegisterClassA(&cls);
win = CreateWindowA( "InSendMessage_test", NULL, 0, 0, 0, 0, 0, NULL, 0, NULL, 0 ); ok( win != NULL, "CreateWindow failed: %d\n", GetLastError() );
thread = CreateThread( NULL, 0, send_message_thread, win, 0, &tid ); ok( thread != NULL, "CreateThread failed: %d\n", GetLastError() );
while (GetMessageA(&msg, NULL, 0, 0)) DispatchMessageA( &msg );
ok( WaitForSingleObject( thread, 30000 ) == WAIT_OBJECT_0, "WaitForSingleObject failed\n" ); CloseHandle( thread );
DestroyWindow( win ); UnregisterClassA( "InSendMessage_test", GetModuleHandleA(NULL) );}
static const struct message DoubleSetCaptureSeq[] ={ { WM_CAPTURECHANGED, sent }, { 0 }};
static void test_DoubleSetCapture(void){ HWND hwnd;
hwnd = CreateWindowExA(0, "TestWindowClass", "Test DoubleSetCapture", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 200, 200, 0, 0, 0, NULL); ok (hwnd != 0, "Failed to create overlapped window\n");
ShowWindow( hwnd, SW_SHOW ); UpdateWindow( hwnd ); flush_events(); flush_sequence();
SetCapture( hwnd ); SetCapture( hwnd ); ok_sequence(DoubleSetCaptureSeq, "SetCapture( hwnd ) twice", FALSE);
DestroyWindow(hwnd);}
static const struct message WmRestoreMinimizedSeq[] ={ { HCBT_ACTIVATE, hook }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { WM_ACTIVATEAPP, sent|wparam, 1 }, { WM_NCACTIVATE, sent|wparam, 0x200001 }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ACTIVATE, sent|wparam, 0x200001 }, /* Note that activate messages are after WM_WINDOWPOSCHANGED and before WM_SYSCOMMAND */ { HCBT_KEYSKIPPED, hook|optional }, { WM_SYSKEYUP, sent|optional }, { WM_SYSCOMMAND, sent|wparam, SC_RESTORE }, { HCBT_SYSCOMMAND, hook|wparam, SC_RESTORE }, { HCBT_SYSCOMMAND, hook|wparam|optional, SC_RESTORE }, { HCBT_MINMAX, hook }, { HCBT_MINMAX, hook|optional }, { WM_QUERYOPEN, sent|defwinproc }, { WM_QUERYOPEN, sent|optional }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, { WM_GETMINMAXINFO, sent|defwinproc }, { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 }, { WM_NCPAINT, sent|wparam|defwinproc|optional, 1 }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent|defwinproc }, { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|defwinproc }, { WM_NCCALCSIZE, sent|wparam|defwinproc|optional, 1 }, { WM_NCPAINT, sent|wparam|defwinproc|optional, 1 }, { WM_ERASEBKGND, sent|defwinproc|optional }, { HCBT_SETFOCUS, hook }, { WM_SETFOCUS, sent|defwinproc }, { WM_ACTIVATE, sent|wparam|defwinproc, 1 }, { WM_PAINT, sent| optional }, { WM_SETFOCUS, sent|defwinproc|optional }, { HCBT_KEYSKIPPED, hook|optional }, { WM_KEYUP, sent|optional }, { HCBT_KEYSKIPPED, hook|optional }, { WM_SYSKEYUP, sent|optional }, { HCBT_KEYSKIPPED, hook|optional }, { WM_KEYUP, sent|optional }, { WM_PAINT, sent| optional }, { 0 }};
static void test_restore_messages(void){ INPUT ip = {0}; HWND hwnd; INT i;
hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 200, 200, 0, 0, 0, NULL); ok (hwnd != 0, "Failed to create overlapped window\n"); SetForegroundWindow(hwnd); ShowWindow(hwnd, SW_MINIMIZE); flush_events(); flush_sequence();
for (i = 0; i < 5; i++) { /* Send Alt+Tab to restore test window from minimized state */ ip.type = INPUT_KEYBOARD; ip.ki.wVk = VK_MENU; SendInput(1, &ip, sizeof(INPUT)); ip.ki.wVk = VK_TAB; SendInput(1, &ip, sizeof(INPUT)); ip.ki.wVk = VK_MENU; ip.ki.dwFlags = KEYEVENTF_KEYUP; SendInput(1, &ip, sizeof(INPUT)); ip.ki.wVk = VK_TAB; ip.ki.dwFlags = KEYEVENTF_KEYUP; SendInput(1, &ip, sizeof(INPUT)); flush_events(); if (!IsIconic(hwnd)) break; }
if (IsIconic(hwnd)) { skip("Alt+Tab failed to bring up test window.\n"); goto done; } ok_sequence(WmRestoreMinimizedSeq, "Restore minimized window", TRUE);
done: DestroyWindow(hwnd);}
static void test_invalid_window(void){ MSG msg; BOOL ret;
SetLastError(0xdeadbeef); ret = GetMessageA(&msg, (HWND)0xdeadbeef, 0, 0); ok(ret == -1, "wrong ret %d\n", ret); ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError());
SetLastError(0xdeadbeef); ret = PeekMessageA(&msg, (HWND)0xdeadbeef, 0, 0, PM_REMOVE); ok(!ret, "wrong ret %d\n", ret); ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError());}
static void init_funcs(void){ HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
#define X(f) p##f = (void*)GetProcAddress(hKernel32, #f) X(ActivateActCtx); X(CreateActCtxW); X(DeactivateActCtx); X(GetCurrentActCtx); X(QueryActCtxW); X(ReleaseActCtx);#undef X}
#ifndef __REACTOS__START_TEST(msg){ char **test_argv; BOOL ret; BOOL (WINAPI *pIsWinEventHookInstalled)(DWORD)= 0;/*GetProcAddress(user32, "IsWinEventHookInstalled");*/ HMODULE hModuleImm32; BOOL (WINAPI *pImmDisableIME)(DWORD); int argc;
init_funcs();
argc = winetest_get_mainargs( &test_argv ); if (argc >= 3) { unsigned int arg; /* Child process. */ sscanf (test_argv[2], "%d", (unsigned int *) &arg); do_wait_idle_child( arg ); return; }
InitializeCriticalSection( &sequence_cs ); init_procs();
hModuleImm32 = LoadLibraryA("imm32.dll"); if (hModuleImm32) { pImmDisableIME = (void *)GetProcAddress(hModuleImm32, "ImmDisableIME"); if (pImmDisableIME) pImmDisableIME(0); } pImmDisableIME = NULL; FreeLibrary(hModuleImm32);
if (!RegisterWindowClasses()) assert(0);
if (pSetWinEventHook) { hEvent_hook = pSetWinEventHook(EVENT_MIN, EVENT_MAX, GetModuleHandleA(0), win_event_proc, 0, GetCurrentThreadId(), WINEVENT_INCONTEXT); if (pIsWinEventHookInstalled && hEvent_hook) { UINT event; for (event = EVENT_MIN; event <= EVENT_MAX; event++) ok(pIsWinEventHookInstalled(event), "IsWinEventHookInstalled(%u) failed\n", event); } } if (!hEvent_hook) win_skip( "no win event hook support\n" );
cbt_hook_thread_id = GetCurrentThreadId(); hCBT_hook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId()); if (!hCBT_hook) win_skip( "cannot set global hook, will skip hook tests\n" );
test_winevents();
/* Fix message sequences before removing 4 lines below */ if (pUnhookWinEvent && hEvent_hook) { ret = pUnhookWinEvent(hEvent_hook); ok( ret, "UnhookWinEvent error %d\n", GetLastError()); pUnhookWinEvent = 0; } hEvent_hook = 0;
test_SendMessage_other_thread(1); test_SendMessage_other_thread(2); test_InSendMessage(); test_SetFocus(); test_SetParent(); test_PostMessage(); test_broadcast(); test_ShowWindow(); test_PeekMessage(); test_PeekMessage2(); test_PeekMessage3(); test_WaitForInputIdle( test_argv[0] ); test_scrollwindowex(); test_messages(); test_setwindowpos(); test_showwindow(); test_recursive_activation(); invisible_parent_tests(); test_mdi_messages(); test_button_messages(); test_button_bm_get_set_image(); test_autoradio_BM_CLICK(); test_autoradio_kbd_move(); test_static_messages(); test_listbox_messages(); test_combobox_messages(); test_wmime_keydown_message(); test_paint_messages(); test_interthread_messages(); test_message_conversion(); test_accelerators(); test_timers(); test_timers_no_wnd(); test_timers_exceptions(); if (hCBT_hook) { test_set_hook(); test_recursive_hook(); } test_DestroyWindow(); test_DispatchMessage(); test_SendMessageTimeout(); test_edit_messages(); test_quit_message(); test_notify_message(); test_SetActiveWindow(); test_restore_messages(); test_invalid_window();
if (!pTrackMouseEvent) win_skip("TrackMouseEvent is not available\n"); else test_TrackMouseEvent();
test_SetWindowRgn(); test_sys_menu(); test_dialog_messages(); test_EndDialog(); test_nullCallback(); test_dbcs_wm_char(); test_unicode_wm_char(); test_menu_messages(); test_paintingloop(); test_defwinproc(); test_desktop_winproc(); test_clipboard_viewers(); test_keyflags(); test_hotkey(); test_layered_window(); test_TrackPopupMenu(); test_TrackPopupMenuEmpty(); test_DoubleSetCapture(); /* keep it the last test, under Windows it tends to break the tests * which rely on active/foreground windows being correct. */ test_SetForegroundWindow();
UnhookWindowsHookEx(hCBT_hook); if (pUnhookWinEvent && hEvent_hook) { ret = pUnhookWinEvent(hEvent_hook); ok( ret, "UnhookWinEvent error %d\n", GetLastError()); SetLastError(0xdeadbeef); ok(!pUnhookWinEvent(hEvent_hook), "UnhookWinEvent succeeded\n"); ok(GetLastError() == ERROR_INVALID_HANDLE || /* Win2k */ GetLastError() == 0xdeadbeef, /* Win9x */ "unexpected error %d\n", GetLastError()); } DeleteCriticalSection( &sequence_cs );}#endif /* __REACTOS__ */
static void init_tests(){ HMODULE hModuleImm32; BOOL (WINAPI *pImmDisableIME)(DWORD);
init_funcs();
InitializeCriticalSection( &sequence_cs ); init_procs();
hModuleImm32 = LoadLibraryA("imm32.dll"); if (hModuleImm32) { pImmDisableIME = (void *)GetProcAddress(hModuleImm32, "ImmDisableIME"); if (pImmDisableIME) pImmDisableIME(0); } pImmDisableIME = NULL; FreeLibrary(hModuleImm32);
if (!RegisterWindowClasses()) assert(0);
cbt_hook_thread_id = GetCurrentThreadId(); hCBT_hook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId()); if (!hCBT_hook) win_skip( "cannot set global hook, will skip hook tests\n" );}
static void cleanup_tests(){ BOOL ret; UnhookWindowsHookEx(hCBT_hook); if (pUnhookWinEvent && hEvent_hook) { ret = pUnhookWinEvent(hEvent_hook); ok( ret, "UnhookWinEvent error %d\n", GetLastError()); SetLastError(0xdeadbeef); ok(!pUnhookWinEvent(hEvent_hook), "UnhookWinEvent succeeded\n"); ok(GetLastError() == ERROR_INVALID_HANDLE || /* Win2k */ GetLastError() == 0xdeadbeef, /* Win9x */ "unexpected error %d\n", GetLastError()); } DeleteCriticalSection( &sequence_cs );
}
START_TEST(msg_queue){ int argc; char **test_argv; argc = winetest_get_mainargs( &test_argv ); if (argc >= 3) { unsigned int arg; /* Child process. */ sscanf (test_argv[2], "%d", (unsigned int *) &arg); do_wait_idle_child( arg ); return; }
init_tests(); test_SendMessage_other_thread(1); test_SendMessage_other_thread(2); test_InSendMessage(); test_PostMessage(); test_broadcast(); test_PeekMessage(); test_PeekMessage2(); test_PeekMessage3(); test_interthread_messages(); test_DispatchMessage(); test_SendMessageTimeout(); test_quit_message(); test_notify_message(); test_WaitForInputIdle( test_argv[0] ); test_DestroyWindow(); cleanup_tests();}
START_TEST(msg_messages){ init_tests(); test_message_conversion(); test_messages(); test_wmime_keydown_message(); test_nullCallback(); test_dbcs_wm_char(); test_unicode_wm_char(); test_defwinproc(); test_desktop_winproc(); cleanup_tests();}
START_TEST(msg_focus){ init_tests();
test_SetFocus();
/* HACK: For some reason the tests fail on Windows if run consecutively. * Putting these in between helps, and is essentially what happens in the * "normal" msg test. */ keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); flush_events();
test_SetActiveWindow();
/* HACK */ keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); flush_events();
test_restore_messages(); test_invalid_window();
test_DoubleSetCapture();
/* keep it the last test, under Windows it tends to break the tests * which rely on active/foreground windows being correct. */ test_SetForegroundWindow(); cleanup_tests();}
START_TEST(msg_winpos){ init_tests(); test_SetParent(); test_ShowWindow(); test_setwindowpos(); test_showwindow(); test_recursive_activation(); test_SetWindowRgn(); invisible_parent_tests(); cleanup_tests();}
START_TEST(msg_paint){ init_tests(); test_scrollwindowex(); test_paint_messages();#ifdef __REACTOS__ if (!winetest_interactive && !strcmp(winetest_platform, "windows")) { skip("ROSTESTS-185: Skipping user32_winetest:msg_paint test_paintingloop because it hangs on WHS-Testbot. Set winetest_interactive to run it anyway.\n"); } else#endif test_paintingloop(); cleanup_tests();}
START_TEST(msg_input){ init_tests(); test_accelerators(); if (!pTrackMouseEvent) win_skip("TrackMouseEvent is not available\n"); else test_TrackMouseEvent();
test_keyflags(); test_hotkey(); cleanup_tests();}
START_TEST(msg_timer){ init_tests(); test_timers(); test_timers_no_wnd(); test_timers_exceptions(); cleanup_tests();}
typedef BOOL (WINAPI *IS_WINEVENT_HOOK_INSTALLED)(DWORD);
START_TEST(msg_hook){// HMODULE user32 = GetModuleHandleA("user32.dll");// IS_WINEVENT_HOOK_INSTALLED pIsWinEventHookInstalled = (IS_WINEVENT_HOOK_INSTALLED)GetProcAddress(user32, "IsWinEventHookInstalled"); BOOL (WINAPI *pIsWinEventHookInstalled)(DWORD)= 0;/*GetProcAddress(user32, "IsWinEventHookInstalled");*/
init_tests();
if (pSetWinEventHook) { hEvent_hook = pSetWinEventHook(EVENT_MIN, EVENT_MAX, GetModuleHandleA(0), win_event_proc, 0, GetCurrentThreadId(), WINEVENT_INCONTEXT); if (pIsWinEventHookInstalled && hEvent_hook) { UINT event; for (event = EVENT_MIN; event <= EVENT_MAX; event++) ok(pIsWinEventHookInstalled(event), "IsWinEventHookInstalled(%u) failed\n", event); } } if (!hEvent_hook) win_skip( "no win event hook support\n" );
test_winevents();
/* Fix message sequences before removing 4 lines below */ if (pUnhookWinEvent && hEvent_hook) { BOOL ret; ret = pUnhookWinEvent(hEvent_hook); ok( ret, "UnhookWinEvent error %d\n", GetLastError()); pUnhookWinEvent = 0; } hEvent_hook = 0; if (hCBT_hook) { test_set_hook(); test_recursive_hook(); } cleanup_tests();}
START_TEST(msg_menu){ init_tests(); test_sys_menu(); test_menu_messages(); test_TrackPopupMenu(); test_TrackPopupMenuEmpty(); cleanup_tests();}
START_TEST(msg_mdi){ init_tests(); test_mdi_messages(); cleanup_tests();}
START_TEST(msg_controls){ init_tests(); test_button_messages(); test_button_bm_get_set_image(); test_autoradio_BM_CLICK(); test_autoradio_kbd_move(); test_static_messages(); test_listbox_messages(); test_combobox_messages(); test_edit_messages(); cleanup_tests();}
START_TEST(msg_layered_window){ init_tests(); test_layered_window(); cleanup_tests();}
START_TEST(msg_dialog){ init_tests(); test_dialog_messages(); test_EndDialog(); cleanup_tests();}
START_TEST(msg_clipboard){ init_tests(); test_clipboard_viewers(); cleanup_tests();}