Something went wrong. Try again.
Reactos
Something went wrong. Try again.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767/* * ListView tests * * Copyright 2006 Mike McCormack for CodeWeavers * Copyright 2007 George Gov * Copyright 2009-2014 Nikolay Sivov * * 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 <stdio.h>#include <windows.h>#include <commctrl.h>
#include "wine/test.h"#include "v6util.h"#include "msg.h"
static HIMAGELIST (WINAPI *pImageList_Create)(int, int, UINT, int, int);static BOOL (WINAPI *pImageList_Destroy)(HIMAGELIST);static int (WINAPI *pImageList_Add)(HIMAGELIST, HBITMAP, HBITMAP);static BOOL (WINAPI *p_TrackMouseEvent)(TRACKMOUSEEVENT *);
enum seq_index { PARENT_SEQ_INDEX, PARENT_FULL_SEQ_INDEX, PARENT_CD_SEQ_INDEX, LISTVIEW_SEQ_INDEX, EDITBOX_SEQ_INDEX, COMBINED_SEQ_INDEX, NUM_MSG_SEQUENCES};
#define LISTVIEW_ID 0#define HEADER_ID 1
#define expect(expected, got) ok(got == expected, "Expected %d, got %d\n", expected, got)#define expect2(expected1, expected2, got1, got2) ok(expected1 == got1 && expected2 == got2, \ "expected (%d,%d), got (%d,%d)\n", expected1, expected2, got1, got2)
static const WCHAR testparentclassW[] = {'L','i','s','t','v','i','e','w',' ','t','e','s','t',' ','p','a','r','e','n','t','W', 0};
static HWND hwndparent, hwndparentW;/* prevents edit box creation, LVN_BEGINLABELEDIT return value */static BOOL blockEdit;/* return nonzero on NM_HOVER */static BOOL g_block_hover;/* notification data for LVN_ITEMCHANGED */static NMLISTVIEW g_nmlistview;/* notification data for LVN_ITEMCHANGING */static NMLISTVIEW g_nmlistview_changing;/* format reported to control: -1 falls to defproc, anything else returned */static INT notifyFormat;/* indicates we're running < 5.80 version */static BOOL g_is_below_5;/* item data passed to LVN_GETDISPINFOA */static LVITEMA g_itema;/* alter notification code A->W */static BOOL g_disp_A_to_W;/* dispinfo data sent with LVN_LVN_ENDLABELEDIT */static NMLVDISPINFOA g_editbox_disp_info;/* when this is set focus will be tested on LVN_DELETEITEM */static BOOL g_focus_test_LVN_DELETEITEM;/* Whether to send WM_KILLFOCUS to the edit control during LVN_ENDLABELEDIT */static BOOL g_WM_KILLFOCUS_on_LVN_ENDLABELEDIT;
static HWND subclass_editbox(HWND hwndListview);
static void init_functions(void){ HMODULE hComCtl32 = LoadLibraryA("comctl32.dll");
#define X(f) p##f = (void*)GetProcAddress(hComCtl32, #f); X(ImageList_Create); X(ImageList_Destroy); X(ImageList_Add); X(_TrackMouseEvent);#undef X}
static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
static const struct message create_ownerdrawfixed_parent_seq[] = { { WM_NOTIFYFORMAT, sent }, { WM_QUERYUISTATE, sent|optional }, /* Win2K and higher */ { WM_MEASUREITEM, sent }, { WM_PARENTNOTIFY, sent }, { 0 }};
static const struct message redraw_listview_seq[] = { { WM_PAINT, sent|id, 0, 0, LISTVIEW_ID }, { WM_PAINT, sent|id, 0, 0, HEADER_ID }, { WM_NCPAINT, sent|id|defwinproc, 0, 0, HEADER_ID }, { WM_ERASEBKGND, sent|id|defwinproc|optional, 0, 0, HEADER_ID }, { WM_NOTIFY, sent|id|defwinproc, 0, 0, LISTVIEW_ID }, { WM_NCPAINT, sent|id|defwinproc, 0, 0, LISTVIEW_ID }, { WM_ERASEBKGND, sent|id|defwinproc|optional, 0, 0, LISTVIEW_ID }, { 0 }};
static const struct message listview_icon_spacing_seq[] = { { LVM_SETICONSPACING, sent|lparam, 0, MAKELPARAM(20, 30) }, { LVM_SETICONSPACING, sent|lparam, 0, MAKELPARAM(25, 35) }, { LVM_SETICONSPACING, sent|lparam, 0, MAKELPARAM(-1, -1) }, { 0 }};
static const struct message listview_color_seq[] = { { LVM_SETBKCOLOR, sent|lparam, 0, RGB(0,0,0) }, { LVM_GETBKCOLOR, sent }, { LVM_SETTEXTCOLOR, sent|lparam, 0, RGB(0,0,0) }, { LVM_GETTEXTCOLOR, sent }, { LVM_SETTEXTBKCOLOR, sent|lparam, 0, RGB(0,0,0) }, { LVM_GETTEXTBKCOLOR, sent },
{ LVM_SETBKCOLOR, sent|lparam, 0, RGB(100,50,200) }, { LVM_GETBKCOLOR, sent }, { LVM_SETTEXTCOLOR, sent|lparam, 0, RGB(100,50,200) }, { LVM_GETTEXTCOLOR, sent }, { LVM_SETTEXTBKCOLOR, sent|lparam, 0, RGB(100,50,200) }, { LVM_GETTEXTBKCOLOR, sent },
{ LVM_SETBKCOLOR, sent|lparam, 0, CLR_NONE }, { LVM_GETBKCOLOR, sent }, { LVM_SETTEXTCOLOR, sent|lparam, 0, CLR_NONE }, { LVM_GETTEXTCOLOR, sent }, { LVM_SETTEXTBKCOLOR, sent|lparam, 0, CLR_NONE }, { LVM_GETTEXTBKCOLOR, sent },
{ LVM_SETBKCOLOR, sent|lparam, 0, RGB(255,255,255) }, { LVM_GETBKCOLOR, sent }, { LVM_SETTEXTCOLOR, sent|lparam, 0, RGB(255,255,255) }, { LVM_GETTEXTCOLOR, sent }, { LVM_SETTEXTBKCOLOR, sent|lparam, 0, RGB(255,255,255) }, { LVM_GETTEXTBKCOLOR, sent }, { 0 }};
static const struct message listview_item_count_seq[] = { { LVM_GETITEMCOUNT, sent }, { LVM_INSERTITEMA, sent }, { LVM_INSERTITEMA, sent }, { LVM_INSERTITEMA, sent }, { LVM_GETITEMCOUNT, sent }, { LVM_DELETEITEM, sent|wparam, 2 }, { WM_NCPAINT, sent|optional }, { WM_ERASEBKGND, sent|optional }, { LVM_GETITEMCOUNT, sent }, { LVM_DELETEALLITEMS, sent }, { LVM_GETITEMCOUNT, sent }, { LVM_INSERTITEMA, sent }, { LVM_INSERTITEMA, sent }, { LVM_GETITEMCOUNT, sent }, { LVM_INSERTITEMA, sent }, { LVM_GETITEMCOUNT, sent }, { 0 }};
static const struct message listview_itempos_seq[] = { { LVM_INSERTITEMA, sent }, { LVM_INSERTITEMA, sent }, { LVM_INSERTITEMA, sent }, { LVM_SETITEMPOSITION, sent|wparam|lparam, 1, MAKELPARAM(10,5) }, { WM_NCPAINT, sent|optional }, { WM_ERASEBKGND, sent|optional }, { LVM_GETITEMPOSITION, sent|wparam, 1 }, { LVM_SETITEMPOSITION, sent|wparam|lparam, 2, MAKELPARAM(0,0) }, { LVM_GETITEMPOSITION, sent|wparam, 2 }, { LVM_SETITEMPOSITION, sent|wparam|lparam, 0, MAKELPARAM(20,20) }, { LVM_GETITEMPOSITION, sent|wparam, 0 }, { 0 }};
static const struct message listview_ownerdata_switchto_seq[] = { { WM_STYLECHANGING, sent }, { WM_STYLECHANGED, sent }, { 0 }};
static const struct message listview_getorderarray_seq[] = { { LVM_GETCOLUMNORDERARRAY, sent|id|wparam, 2, 0, LISTVIEW_ID }, { HDM_GETORDERARRAY, sent|id|wparam, 2, 0, HEADER_ID }, { LVM_GETCOLUMNORDERARRAY, sent|id|wparam, 0, 0, LISTVIEW_ID }, { HDM_GETORDERARRAY, sent|id|wparam, 0, 0, HEADER_ID }, { 0 }};
static const struct message listview_setorderarray_seq[] = { { LVM_SETCOLUMNORDERARRAY, sent|id|wparam, 2, 0, LISTVIEW_ID }, { HDM_SETORDERARRAY, sent|id|wparam, 2, 0, HEADER_ID }, { LVM_SETCOLUMNORDERARRAY, sent|id|wparam, 0, 0, LISTVIEW_ID }, { HDM_SETORDERARRAY, sent|id|wparam, 0, 0, HEADER_ID }, { 0 }};
static const struct message empty_seq[] = { { 0 }};
static const struct message parent_focus_change_ownerdata_seq[] = { { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED }, { WM_NOTIFY, sent|id, 0, 0, LVN_GETDISPINFOA }, { 0 }};
static const struct message forward_erasebkgnd_parent_seq[] = { { WM_ERASEBKGND, sent }, { 0 }};
static const struct message ownerdata_select_focus_parent_seq[] = { { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED }, { WM_NOTIFY, sent|id, 0, 0, LVN_GETDISPINFOA }, { WM_NOTIFY, sent|id|optional, 0, 0, LVN_GETDISPINFOA }, /* version 4.7x */ { 0 }};
static const struct message ownerdata_setstate_all_parent_seq[] = { { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED }, { 0 }};
static const struct message ownerdata_defocus_all_parent_seq[] = { { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED }, { WM_NOTIFY, sent|id, 0, 0, LVN_GETDISPINFOA }, { WM_NOTIFY, sent|id|optional, 0, 0, LVN_GETDISPINFOA }, { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED }, { 0 }};
static const struct message ownerdata_deselect_all_parent_seq[] = { { WM_NOTIFY, sent|id, 0, 0, LVN_ODCACHEHINT }, { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED }, { 0 }};
static const struct message change_all_parent_seq[] = { { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING }, { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
{ WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING }, { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
{ WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING }, { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
{ WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING }, { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
{ WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING }, { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED }, { 0 }};
static const struct message changing_all_parent_seq[] = { { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING }, { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING }, { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING }, { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING }, { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING }, { 0 }};
static const struct message textcallback_set_again_parent_seq[] = { { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING }, { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED }, { 0 }};
static const struct message single_getdispinfo_parent_seq[] = { { WM_NOTIFY, sent|id, 0, 0, LVN_GETDISPINFOA }, { 0 }};
static const struct message getitemposition_seq1[] = { { LVM_GETITEMPOSITION, sent|id, 0, 0, LISTVIEW_ID }, { 0 }};
static const struct message getitemposition_seq2[] = { { LVM_GETITEMPOSITION, sent|id, 0, 0, LISTVIEW_ID }, { HDM_GETITEMRECT, sent|id, 0, 0, HEADER_ID }, { 0 }};
static const struct message getsubitemrect_seq[] = { { LVM_GETSUBITEMRECT, sent|id|wparam, -1, 0, LISTVIEW_ID }, { HDM_GETITEMRECT, sent|id, 0, 0, HEADER_ID }, { LVM_GETSUBITEMRECT, sent|id|wparam, 0, 0, LISTVIEW_ID }, { HDM_GETITEMRECT, sent|id, 0, 0, HEADER_ID }, { LVM_GETSUBITEMRECT, sent|id|wparam, -10, 0, LISTVIEW_ID }, { HDM_GETITEMRECT, sent|id, 0, 0, HEADER_ID }, { LVM_GETSUBITEMRECT, sent|id|wparam, 20, 0, LISTVIEW_ID }, { HDM_GETITEMRECT, sent|id, 0, 0, HEADER_ID }, { 0 }};
static const struct message editbox_create_pos[] = { /* sequence sent after LVN_BEGINLABELEDIT */ /* next two are 4.7x specific */ { WM_WINDOWPOSCHANGING, sent }, { WM_WINDOWPOSCHANGED, sent|optional },
{ WM_WINDOWPOSCHANGING, sent|optional }, { WM_NCCALCSIZE, sent }, { WM_WINDOWPOSCHANGED, sent }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|defwinproc }, /* the rest is todo, skipped in 4.7x */ { WM_WINDOWPOSCHANGING, sent|optional }, { WM_WINDOWPOSCHANGED, sent|optional }, { 0 }};
static const struct message scroll_parent_seq[] = { { WM_NOTIFY, sent|id, 0, 0, LVN_BEGINSCROLL }, { WM_NOTIFY, sent|id, 0, 0, LVN_ENDSCROLL }, { 0 }};
static const struct message setredraw_seq[] = { { WM_SETREDRAW, sent|id|wparam, FALSE, 0, LISTVIEW_ID }, { 0 }};
static const struct message lvs_ex_transparentbkgnd_seq[] = { { WM_PRINTCLIENT, sent|lparam, 0, PRF_ERASEBKGND }, { 0 }};
static const struct message edit_end_nochange[] = { { WM_NOTIFY, sent|id, 0, 0, LVN_ENDLABELEDITA }, { WM_NOTIFY, sent|id, 0, 0, NM_CUSTOMDRAW }, /* todo */ { WM_NOTIFY, sent|id, 0, 0, NM_SETFOCUS }, { 0 }};
static const struct message hover_parent[] = { { WM_GETDLGCODE, sent }, /* todo_wine */ { WM_NOTIFY, sent|id, 0, 0, NM_HOVER }, { 0 }};
static const struct message listview_destroy[] = { { 0x0090, sent|optional }, /* Vista */ { WM_PARENTNOTIFY, sent }, { WM_SHOWWINDOW, sent }, { WM_WINDOWPOSCHANGING, sent }, { WM_WINDOWPOSCHANGED, sent|optional }, { WM_DESTROY, sent }, { WM_NOTIFY, sent|id, 0, 0, LVN_DELETEALLITEMS }, { WM_NCDESTROY, sent }, { 0 }};
static const struct message listview_ownerdata_destroy[] = { { 0x0090, sent|optional }, /* Vista */ { WM_PARENTNOTIFY, sent }, { WM_SHOWWINDOW, sent }, { WM_WINDOWPOSCHANGING, sent }, { WM_WINDOWPOSCHANGED, sent|optional }, { WM_DESTROY, sent }, { WM_NCDESTROY, sent }, { 0 }};
static const struct message listview_ownerdata_deleteall[] = { { LVM_DELETEALLITEMS, sent }, { WM_NOTIFY, sent|id, 0, 0, LVN_DELETEALLITEMS }, { 0 }};
static const struct message listview_header_changed_seq[] = { { LVM_SETCOLUMNA, sent }, { WM_NOTIFY, sent|id|defwinproc, 0, 0, LISTVIEW_ID }, { WM_NOTIFY, sent|id|defwinproc, 0, 0, LISTVIEW_ID }, { 0 }};
static const struct message parent_header_click_seq[] = { { WM_NOTIFY, sent|id, 0, 0, LVN_COLUMNCLICK }, { WM_NOTIFY, sent|id, 0, 0, HDN_ITEMCLICKA }, { 0 }};
static const struct message parent_header_divider_dclick_seq[] = { { WM_NOTIFY, sent|id, 0, 0, HDN_ITEMCHANGINGA }, { WM_NOTIFY, sent|id, 0, 0, NM_CUSTOMDRAW }, { WM_NOTIFY, sent|id, 0, 0, NM_CUSTOMDRAW }, { WM_NOTIFY, sent|id, 0, 0, HDN_ITEMCHANGEDA }, { WM_NOTIFY, sent|id, 0, 0, HDN_DIVIDERDBLCLICKA }, { 0 }};
static const struct message listview_set_imagelist[] = { { LVM_SETIMAGELIST, sent|id, 0, 0, LISTVIEW_ID }, { 0 }};
static const struct message listview_header_set_imagelist[] = { { LVM_SETIMAGELIST, sent|id, 0, 0, LISTVIEW_ID }, { HDM_SETIMAGELIST, sent|id, 0, 0, HEADER_ID }, { 0 }};
static const struct message parent_insert_focused_seq[] = { { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING }, { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING }, { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED }, { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED }, { WM_NOTIFY, sent|id, 0, 0, LVN_INSERTITEM }, { 0 }};
static const struct message parent_report_cd_seq[] = { { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_PREPAINT }, { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_ITEMPREPAINT }, { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_ITEMPREPAINT|CDDS_SUBITEM }, { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_ITEMPOSTPAINT|CDDS_SUBITEM }, { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_ITEMPREPAINT|CDDS_SUBITEM }, { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_ITEMPOSTPAINT|CDDS_SUBITEM }, { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_ITEMPOSTPAINT }, { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_POSTPAINT }, { 0 }};
static const struct message parent_list_cd_seq[] = { { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_PREPAINT }, { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_ITEMPREPAINT }, { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_ITEMPOSTPAINT }, { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_POSTPAINT }, { 0 }};
static const struct message listview_end_label_edit[] = { { WM_NOTIFY, sent|id, 0, 0, LVN_ENDLABELEDITA }, { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING}, { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED }, { WM_NOTIFY, sent|id|optional, 0, 0, NM_CUSTOMDRAW }, /* XP */ { WM_NOTIFY, sent|id, 0, 0, NM_SETFOCUS }, { 0 }};
static const struct message listview_end_label_edit_kill_focus[] = { { WM_NOTIFY, sent|id, 0, 0, LVN_ENDLABELEDITA }, { WM_COMMAND, sent|id|optional, 0, 0, EN_KILLFOCUS }, /* todo: not sent by wine yet */ { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING }, { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED }, { WM_NOTIFY, sent|id|optional, 0, 0, NM_CUSTOMDRAW }, /* XP */ { WM_NOTIFY, sent|id, 0, 0, NM_SETFOCUS }, { 0 }};
static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ static LONG defwndproc_counter = 0; LRESULT ret; struct message msg;
msg.message = message; msg.flags = sent|wparam|lparam; if (defwndproc_counter) msg.flags |= defwinproc; msg.wParam = wParam; msg.lParam = lParam; if (message == WM_NOTIFY && lParam) msg.id = ((NMHDR*)lParam)->code; if (message == WM_COMMAND) msg.id = HIWORD(wParam);
/* log system messages, except for painting */ if (message < WM_USER && message != WM_PAINT && message != WM_ERASEBKGND && message != WM_NCPAINT && message != WM_NCHITTEST && message != WM_GETTEXT && message != WM_GETICON && message != WM_DEVICECHANGE) { add_message(sequences, PARENT_SEQ_INDEX, &msg); add_message(sequences, COMBINED_SEQ_INDEX, &msg); } add_message(sequences, PARENT_FULL_SEQ_INDEX, &msg);
switch (message) { case WM_NOTIFY: { switch (((NMHDR*)lParam)->code) { case LVN_BEGINLABELEDITA: { HWND edit = NULL;
/* subclass edit box */ if (!blockEdit) edit = subclass_editbox(((NMHDR*)lParam)->hwndFrom);
if (edit) { INT len = SendMessageA(edit, EM_GETLIMITTEXT, 0, 0); ok(len == 259 || broken(len == 260) /* includes NULL in NT4 */, "text limit %d, expected 259\n", len); }
return blockEdit; } case LVN_ENDLABELEDITA: { HWND edit;
/* always accept new item text */ NMLVDISPINFOA *di = (NMLVDISPINFOA*)lParam; g_editbox_disp_info = *di;
/* edit control still available from this notification */ edit = (HWND)SendMessageA(((NMHDR*)lParam)->hwndFrom, LVM_GETEDITCONTROL, 0, 0); ok(IsWindow(edit), "expected valid edit control handle\n"); ok((GetWindowLongA(edit, GWL_STYLE) & ES_MULTILINE) == 0, "edit is multiline\n");
if (g_WM_KILLFOCUS_on_LVN_ENDLABELEDIT) SendMessageA(edit, WM_KILLFOCUS, 0, 0);
return TRUE; } case LVN_ITEMCHANGING: { NMLISTVIEW *nmlv = (NMLISTVIEW*)lParam; g_nmlistview_changing = *nmlv; } break; case LVN_ITEMCHANGED: { NMLISTVIEW *nmlv = (NMLISTVIEW*)lParam; g_nmlistview = *nmlv; } break; case LVN_GETDISPINFOA: { NMLVDISPINFOA *dispinfo = (NMLVDISPINFOA*)lParam; g_itema = dispinfo->item;
if (g_disp_A_to_W && (dispinfo->item.mask & LVIF_TEXT)) { static const WCHAR testW[] = {'T','E','S','T',0}; dispinfo->hdr.code = LVN_GETDISPINFOW; memcpy(dispinfo->item.pszText, testW, sizeof(testW)); }
/* test control buffer size for text, 10 used to mask cases when control is using caller buffer to process LVM_GETITEM for example */ if (dispinfo->item.mask & LVIF_TEXT && dispinfo->item.cchTextMax > 10) ok(dispinfo->item.cchTextMax == 260 || broken(dispinfo->item.cchTextMax == 264) /* NT4 reports aligned size */, "buffer size %d\n", dispinfo->item.cchTextMax); } break; case LVN_DELETEITEM: if (g_focus_test_LVN_DELETEITEM) { NMLISTVIEW *nmlv = (NMLISTVIEW*)lParam; UINT state;
state = SendMessageA(((NMHDR*)lParam)->hwndFrom, LVM_GETITEMSTATE, nmlv->iItem, LVIS_FOCUSED); ok(state == 0, "got state %x\n", state); } break; case NM_HOVER: if (g_block_hover) return 1; break; } break; } case WM_NOTIFYFORMAT: { /* force to return format */ if (lParam == NF_QUERY && notifyFormat != -1) return notifyFormat; break; } }
defwndproc_counter++; if (IsWindowUnicode(hwnd)) ret = DefWindowProcW(hwnd, message, wParam, lParam); else ret = DefWindowProcA(hwnd, message, wParam, lParam); defwndproc_counter--;
return ret;}
static BOOL register_parent_wnd_class(BOOL Unicode){ WNDCLASSA clsA; WNDCLASSW clsW;
if (Unicode) { clsW.style = 0; clsW.lpfnWndProc = parent_wnd_proc; clsW.cbClsExtra = 0; clsW.cbWndExtra = 0; clsW.hInstance = GetModuleHandleW(NULL); clsW.hIcon = 0; clsW.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); clsW.hbrBackground = GetStockObject(WHITE_BRUSH); clsW.lpszMenuName = NULL; clsW.lpszClassName = testparentclassW; } else { clsA.style = 0; clsA.lpfnWndProc = parent_wnd_proc; clsA.cbClsExtra = 0; clsA.cbWndExtra = 0; clsA.hInstance = GetModuleHandleA(NULL); clsA.hIcon = 0; clsA.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); clsA.hbrBackground = GetStockObject(WHITE_BRUSH); clsA.lpszMenuName = NULL; clsA.lpszClassName = "Listview test parent class"; }
return Unicode ? RegisterClassW(&clsW) : RegisterClassA(&clsA);}
static HWND create_parent_window(BOOL Unicode){ static const WCHAR nameW[] = {'t','e','s','t','p','a','r','e','n','t','n','a','m','e','W',0}; HWND hwnd;
if (!register_parent_wnd_class(Unicode)) return NULL;
blockEdit = FALSE; notifyFormat = -1;
if (Unicode) hwnd = CreateWindowExW(0, testparentclassW, nameW, WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_VISIBLE, 0, 0, 100, 100, GetDesktopWindow(), NULL, GetModuleHandleW(NULL), NULL); else hwnd = CreateWindowExA(0, "Listview test parent class", "Listview test parent window", WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_VISIBLE, 0, 0, 100, 100, GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL); SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE ); return hwnd;}
static LRESULT WINAPI listview_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA); static LONG defwndproc_counter = 0; LRESULT ret; struct message msg;
msg.message = message; msg.flags = sent|wparam|lparam; if (defwndproc_counter) msg.flags |= defwinproc; msg.wParam = wParam; msg.lParam = lParam; msg.id = LISTVIEW_ID; add_message(sequences, LISTVIEW_SEQ_INDEX, &msg); add_message(sequences, COMBINED_SEQ_INDEX, &msg);
defwndproc_counter++; ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam); defwndproc_counter--; return ret;}
static HWND create_listview_control(DWORD style){ WNDPROC oldproc; HWND hwnd; RECT rect;
GetClientRect(hwndparent, &rect); hwnd = CreateWindowExA(0, WC_LISTVIEWA, "foo", WS_CHILD | WS_BORDER | WS_VISIBLE | style, 0, 0, rect.right, rect.bottom, hwndparent, NULL, GetModuleHandleA(NULL), NULL); ok(hwnd != NULL, "gle=%d\n", GetLastError());
if (!hwnd) return NULL;
oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONG_PTR)listview_subclass_proc); SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc);
return hwnd;}
/* unicode listview window with specified parent */static HWND create_listview_controlW(DWORD style, HWND parent){ WNDPROC oldproc; HWND hwnd; RECT rect; static const WCHAR nameW[] = {'f','o','o',0};
GetClientRect(parent, &rect); hwnd = CreateWindowExW(0, WC_LISTVIEWW, nameW, WS_CHILD | WS_BORDER | WS_VISIBLE | style, 0, 0, rect.right, rect.bottom, parent, NULL, GetModuleHandleW(NULL), NULL); ok(hwnd != NULL, "gle=%d\n", GetLastError());
if (!hwnd) return NULL;
oldproc = (WNDPROC)SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR)listview_subclass_proc); SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc);
return hwnd;}
static BOOL is_win_xp(void){ HWND hwnd, header; BOOL ret;
hwnd = create_listview_control(LVS_ICON); SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_HEADERINALLVIEWS, LVS_EX_HEADERINALLVIEWS); header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); ret = !IsWindow(header);
DestroyWindow(hwnd);
return ret;}
static LRESULT WINAPI header_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA); static LONG defwndproc_counter = 0; struct message msg = { 0 }; LRESULT ret;
msg.message = message; msg.flags = sent|wparam|lparam; if (defwndproc_counter) msg.flags |= defwinproc; msg.wParam = wParam; msg.lParam = lParam; msg.id = HEADER_ID; add_message(sequences, LISTVIEW_SEQ_INDEX, &msg);
defwndproc_counter++; ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam); defwndproc_counter--; return ret;}
static HWND subclass_header(HWND hwndListview){ WNDPROC oldproc; HWND hwnd;
hwnd = (HWND)SendMessageA(hwndListview, LVM_GETHEADER, 0, 0); oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONG_PTR)header_subclass_proc); SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc);
return hwnd;}
static LRESULT WINAPI editbox_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA); static LONG defwndproc_counter = 0; struct message msg = { 0 }; LRESULT ret;
msg.message = message; msg.flags = sent|wparam|lparam; if (defwndproc_counter) msg.flags |= defwinproc; msg.wParam = wParam; msg.lParam = lParam;
/* all we need is sizing */ if (message == WM_WINDOWPOSCHANGING || message == WM_NCCALCSIZE || message == WM_WINDOWPOSCHANGED || message == WM_MOVE || message == WM_SIZE) { add_message(sequences, EDITBOX_SEQ_INDEX, &msg); }
defwndproc_counter++; ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam); defwndproc_counter--; return ret;}
static HWND subclass_editbox(HWND hwndListview){ WNDPROC oldproc; HWND hwnd;
hwnd = (HWND)SendMessageA(hwndListview, LVM_GETEDITCONTROL, 0, 0); oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONG_PTR)editbox_subclass_proc); SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc);
return hwnd;}
/* Performs a single LVM_HITTEST test */static void test_lvm_hittest_(HWND hwnd, INT x, INT y, INT item, UINT flags, UINT broken_flags, BOOL todo_item, BOOL todo_flags, int line){ LVHITTESTINFO lpht; INT ret;
lpht.pt.x = x; lpht.pt.y = y; lpht.iSubItem = 10;
ret = SendMessageA(hwnd, LVM_HITTEST, 0, (LPARAM)&lpht);
todo_wine_if(todo_item) { ok_(__FILE__, line)(ret == item, "Expected %d retval, got %d\n", item, ret); ok_(__FILE__, line)(lpht.iItem == item, "Expected %d item, got %d\n", item, lpht.iItem); ok_(__FILE__, line)(lpht.iSubItem == 10, "Expected subitem not overwrited\n"); }
if (todo_flags) { todo_wine ok_(__FILE__, line)(lpht.flags == flags, "Expected flags 0x%x, got 0x%x\n", flags, lpht.flags); } else if (broken_flags) ok_(__FILE__, line)(lpht.flags == flags || broken(lpht.flags == broken_flags), "Expected flags %x, got %x\n", flags, lpht.flags); else ok_(__FILE__, line)(lpht.flags == flags, "Expected flags 0x%x, got 0x%x\n", flags, lpht.flags);}
#define test_lvm_hittest(a,b,c,d,e,f,g,h) test_lvm_hittest_(a,b,c,d,e,f,g,h,__LINE__)
/* Performs a single LVM_SUBITEMHITTEST test */static void test_lvm_subitemhittest_(HWND hwnd, INT x, INT y, INT item, INT subitem, UINT flags, BOOL todo_item, BOOL todo_subitem, BOOL todo_flags, int line){ LVHITTESTINFO lpht; INT ret;
lpht.pt.x = x; lpht.pt.y = y;
ret = SendMessageA(hwnd, LVM_SUBITEMHITTEST, 0, (LPARAM)&lpht);
todo_wine_if(todo_item) { ok_(__FILE__, line)(ret == item, "Expected %d retval, got %d\n", item, ret); ok_(__FILE__, line)(lpht.iItem == item, "Expected %d item, got %d\n", item, lpht.iItem); }
todo_wine_if(todo_subitem) ok_(__FILE__, line)(lpht.iSubItem == subitem, "Expected subitem %d, got %d\n", subitem, lpht.iSubItem);
todo_wine_if(todo_flags) ok_(__FILE__, line)(lpht.flags == flags, "Expected flags 0x%x, got 0x%x\n", flags, lpht.flags);}
#define test_lvm_subitemhittest(a,b,c,d,e,f,g,h,i) test_lvm_subitemhittest_(a,b,c,d,e,f,g,h,i,__LINE__)
static void test_images(void){ HWND hwnd; INT r; LVITEMA item; HIMAGELIST himl; HBITMAP hbmp; RECT r1, r2; static CHAR hello[] = "hello";
himl = pImageList_Create(40, 40, 0, 4, 4); ok(himl != NULL, "failed to create imagelist\n");
hbmp = CreateBitmap(40, 40, 1, 1, NULL); ok(hbmp != NULL, "failed to create bitmap\n");
r = pImageList_Add(himl, hbmp, 0); ok(r == 0, "should be zero\n");
hwnd = CreateWindowExA(0, WC_LISTVIEWA, "foo", LVS_OWNERDRAWFIXED, 10, 10, 100, 200, hwndparent, NULL, NULL, NULL); ok(hwnd != NULL, "failed to create listview window\n");
r = SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_UNDERLINEHOT | LVS_EX_FLATSB | LVS_EX_ONECLICKACTIVATE);
ok(r == 0, "should return zero\n");
r = SendMessageA(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)himl); ok(r == 0, "should return zero\n");
r = SendMessageA(hwnd, LVM_SETICONSPACING, 0, MAKELONG(100,50)); ok(r != 0, "got 0\n");
/* returns dimensions */
r = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0); ok(r == 0, "should be zero items\n");
item.mask = LVIF_IMAGE | LVIF_TEXT; item.iItem = 0; item.iSubItem = 1; item.iImage = 0; item.pszText = 0; r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); ok(r == -1, "should fail\n");
item.iSubItem = 0; item.pszText = hello; r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); ok(r == 0, "should not fail\n");
SetRect(&r1, LVIR_ICON, 0, 0, 0); r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM) &r1); expect(1, r);
r = SendMessageA(hwnd, LVM_DELETEALLITEMS, 0, 0); ok(r == TRUE, "should not fail\n");
item.iSubItem = 0; item.pszText = hello; r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); ok(r == 0, "should not fail\n");
SetRect(&r2, LVIR_ICON, 0, 0, 0); r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM) &r2); expect(1, r);
ok(EqualRect(&r1, &r2), "rectangle should be the same\n");
DestroyWindow(hwnd);
/* I_IMAGECALLBACK set for item, try to get image with invalid subitem. */ hwnd = create_listview_control(LVS_REPORT); ok(hwnd != NULL, "Failed to create listview.\n");
memset(&item, 0, sizeof(item)); item.mask = LVIF_IMAGE; item.iImage = I_IMAGECALLBACK; r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item); ok(!r, "Failed to insert item.\n");
flush_sequences(sequences, NUM_MSG_SEQUENCES);
memset(&item, 0, sizeof(item)); item.mask = LVIF_IMAGE; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item); ok(r, "Failed to get item.\n");
ok_sequence(sequences, PARENT_SEQ_INDEX, single_getdispinfo_parent_seq, "get image dispinfo 1", FALSE);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
memset(&item, 0, sizeof(item)); item.mask = LVIF_IMAGE; item.iSubItem = 1; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item); ok(r, "Failed to get item.\n");
ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "get image dispinfo 2", FALSE);
DestroyWindow(hwnd);}
static void test_checkboxes(void){ HWND hwnd; LVITEMA item; DWORD r; static CHAR text[] = "Text", text2[] = "Text2", text3[] = "Text3";
hwnd = CreateWindowExA(0, WC_LISTVIEWA, "foo", LVS_REPORT, 10, 10, 100, 200, hwndparent, NULL, NULL, NULL); ok(hwnd != NULL, "failed to create listview window\n");
/* first without LVS_EX_CHECKBOXES set and an item and check that state is preserved */ item.mask = LVIF_TEXT | LVIF_STATE; item.stateMask = 0xffff; item.state = 0xfccc; item.iItem = 0; item.iSubItem = 0; item.pszText = text; r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); expect(0, r);
item.iItem = 0; item.mask = LVIF_STATE; item.stateMask = 0xffff; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); expect(1, r); ok(item.state == 0xfccc, "state %x\n", item.state);
/* Don't set LVIF_STATE */ item.mask = LVIF_TEXT; item.stateMask = 0xffff; item.state = 0xfccc; item.iItem = 1; item.iSubItem = 0; item.pszText = text; r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); expect(1, r);
item.iItem = 1; item.mask = LVIF_STATE; item.stateMask = 0xffff; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); expect(1, r); ok(item.state == 0, "state %x\n", item.state);
r = SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES); expect(0, r);
/* Having turned on checkboxes, check that all existing items are set to 0x1000 (unchecked) */ item.iItem = 0; item.mask = LVIF_STATE; item.stateMask = 0xffff; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); expect(1, r); if (item.state != 0x1ccc) { win_skip("LVS_EX_CHECKBOXES style is unavailable. Skipping.\n"); DestroyWindow(hwnd); return; }
/* Now add an item without specifying a state and check that its state goes to 0x1000 */ item.iItem = 2; item.mask = LVIF_TEXT; item.state = 0; item.pszText = text2; r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); expect(2, r);
item.iItem = 2; item.mask = LVIF_STATE; item.stateMask = 0xffff; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); expect(1, r); ok(item.state == 0x1000, "state %x\n", item.state);
/* Add a further item this time specifying a state and still its state goes to 0x1000 */ item.iItem = 3; item.mask = LVIF_TEXT | LVIF_STATE; item.stateMask = 0xffff; item.state = 0x2aaa; item.pszText = text3; r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); expect(3, r);
item.iItem = 3; item.mask = LVIF_STATE; item.stateMask = 0xffff; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); expect(1, r); ok(item.state == 0x1aaa, "state %x\n", item.state);
/* Set an item's state to checked */ item.iItem = 3; item.mask = LVIF_STATE; item.stateMask = 0xf000; item.state = 0x2000; r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM) &item); expect(1, r);
item.iItem = 3; item.mask = LVIF_STATE; item.stateMask = 0xffff; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); expect(1, r); ok(item.state == 0x2aaa, "state %x\n", item.state);
/* Check that only the bits we asked for are returned, * and that all the others are set to zero */ item.iItem = 3; item.mask = LVIF_STATE; item.stateMask = 0xf000; item.state = 0xffff; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); expect(1, r); ok(item.state == 0x2000, "state %x\n", item.state);
/* Set the style again and check that doesn't change an item's state */ r = SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES); ok(r == LVS_EX_CHECKBOXES, "ret %x\n", r);
item.iItem = 3; item.mask = LVIF_STATE; item.stateMask = 0xffff; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); expect(1, r); ok(item.state == 0x2aaa, "state %x\n", item.state);
/* Unsetting the checkbox extended style doesn't change an item's state */ r = SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, 0); ok(r == LVS_EX_CHECKBOXES, "ret %x\n", r);
item.iItem = 3; item.mask = LVIF_STATE; item.stateMask = 0xffff; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); expect(1, r); ok(item.state == 0x2aaa, "state %x\n", item.state);
/* Now setting the style again will change an item's state */ r = SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES); expect(0, r);
item.iItem = 3; item.mask = LVIF_STATE; item.stateMask = 0xffff; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); expect(1, r); ok(item.state == 0x1aaa, "state %x\n", item.state);
/* Toggle checkbox tests (bug 9934) */ memset (&item, 0xcc, sizeof(item)); item.mask = LVIF_STATE; item.iItem = 3; item.iSubItem = 0; item.state = LVIS_FOCUSED; item.stateMask = LVIS_FOCUSED; r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM) &item); expect(1, r);
item.iItem = 3; item.mask = LVIF_STATE; item.stateMask = 0xffff; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); expect(1, r); ok(item.state == 0x1aab, "state %x\n", item.state);
r = SendMessageA(hwnd, WM_KEYDOWN, VK_SPACE, 0); expect(0, r); r = SendMessageA(hwnd, WM_KEYUP, VK_SPACE, 0); expect(0, r);
item.iItem = 3; item.mask = LVIF_STATE; item.stateMask = 0xffff; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); expect(1, r); ok(item.state == 0x2aab, "state %x\n", item.state);
r = SendMessageA(hwnd, WM_KEYDOWN, VK_SPACE, 0); expect(0, r); r = SendMessageA(hwnd, WM_KEYUP, VK_SPACE, 0); expect(0, r);
item.iItem = 3; item.mask = LVIF_STATE; item.stateMask = 0xffff; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); expect(1, r); ok(item.state == 0x1aab, "state %x\n", item.state);
DestroyWindow(hwnd);}
static void insert_column(HWND hwnd, int idx){ LVCOLUMNA column; INT rc;
memset(&column, 0xcc, sizeof(column)); column.mask = LVCF_SUBITEM; column.iSubItem = idx;
rc = SendMessageA(hwnd, LVM_INSERTCOLUMNA, idx, (LPARAM)&column); expect(idx, rc);}
static void insert_item(HWND hwnd, int idx){ static CHAR text[] = "foo";
LVITEMA item; INT rc;
memset(&item, 0xcc, sizeof (item)); item.mask = LVIF_TEXT; item.iItem = idx; item.iSubItem = 0; item.pszText = text;
rc = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item); expect(idx, rc);}
static void test_items(void){ const LPARAM lparamTest = 0x42; static CHAR text[] = "Text"; char buffA[5]; HWND hwnd; LVITEMA item; DWORD r;
hwnd = CreateWindowExA(0, WC_LISTVIEWA, "foo", LVS_REPORT, 10, 10, 100, 200, hwndparent, NULL, NULL, NULL); ok(hwnd != NULL, "failed to create listview window\n");
/* * Test setting/getting item params */
/* Set up two columns */ insert_column(hwnd, 0); insert_column(hwnd, 1);
/* LVIS_SELECTED with zero stateMask */ /* set */ memset (&item, 0, sizeof (item)); item.mask = LVIF_STATE; item.state = LVIS_SELECTED; item.stateMask = 0; item.iItem = 0; item.iSubItem = 0; r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); expect(0, r); /* get */ memset (&item, 0xcc, sizeof (item)); item.mask = LVIF_STATE; item.stateMask = LVIS_SELECTED; item.state = 0; item.iItem = 0; item.iSubItem = 0; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); expect(1, r); ok(item.state & LVIS_SELECTED, "Expected LVIS_SELECTED\n"); r = SendMessageA(hwnd, LVM_DELETEITEM, 0, 0); ok(r, "got %d\n", r);
/* LVIS_SELECTED with zero stateMask */ /* set */ memset (&item, 0, sizeof (item)); item.mask = LVIF_STATE; item.state = LVIS_FOCUSED; item.stateMask = 0; item.iItem = 0; item.iSubItem = 0; r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); expect(0, r); /* get */ memset (&item, 0xcc, sizeof (item)); item.mask = LVIF_STATE; item.stateMask = LVIS_FOCUSED; item.state = 0; item.iItem = 0; item.iSubItem = 0; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); expect(1, r); ok(item.state & LVIS_FOCUSED, "Expected LVIS_FOCUSED\n"); r = SendMessageA(hwnd, LVM_DELETEITEM, 0, 0); ok(r, "got %d\n", r);
/* LVIS_CUT with LVIS_FOCUSED stateMask */ /* set */ memset (&item, 0, sizeof (item)); item.mask = LVIF_STATE; item.state = LVIS_CUT; item.stateMask = LVIS_FOCUSED; item.iItem = 0; item.iSubItem = 0; r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); expect(0, r); /* get */ memset (&item, 0xcc, sizeof (item)); item.mask = LVIF_STATE; item.stateMask = LVIS_CUT; item.state = 0; item.iItem = 0; item.iSubItem = 0; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); expect(1, r); ok(item.state & LVIS_CUT, "Expected LVIS_CUT\n"); r = SendMessageA(hwnd, LVM_DELETEITEM, 0, 0); ok(r, "got %d\n", r);
/* Insert an item with just a param */ memset (&item, 0xcc, sizeof (item)); item.mask = LVIF_PARAM; item.iItem = 0; item.iSubItem = 0; item.lParam = lparamTest; r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); expect(0, r);
/* Test getting of the param */ memset (&item, 0xcc, sizeof (item)); item.mask = LVIF_PARAM; item.iItem = 0; item.iSubItem = 0; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); expect(1, r); ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest);
/* Set up a subitem */ memset (&item, 0xcc, sizeof (item)); item.mask = LVIF_TEXT; item.iItem = 0; item.iSubItem = 1; item.pszText = text; r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM) &item); expect(1, r);
item.mask = LVIF_TEXT; item.iItem = 0; item.iSubItem = 1; item.pszText = buffA; item.cchTextMax = sizeof(buffA); r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); expect(1, r); ok(!memcmp(item.pszText, text, sizeof(text)), "got text %s, expected %s\n", item.pszText, text);
/* set up with extra flag */ /* 1. reset subitem text */ item.mask = LVIF_TEXT; item.iItem = 0; item.iSubItem = 1; item.pszText = NULL; r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM) &item); expect(1, r);
item.mask = LVIF_TEXT; item.iItem = 0; item.iSubItem = 1; item.pszText = buffA; buffA[0] = 'a'; item.cchTextMax = sizeof(buffA); r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); expect(1, r); ok(item.pszText[0] == 0, "got %p\n", item.pszText);
/* 2. set new text with extra flag specified */ item.mask = LVIF_TEXT | LVIF_DI_SETITEM; item.iItem = 0; item.iSubItem = 1; item.pszText = text; r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM) &item); ok(r == 1 || broken(r == 0) /* NT4 */, "ret %d\n", r);
if (r == 1) { item.mask = LVIF_TEXT; item.iItem = 0; item.iSubItem = 1; item.pszText = buffA; buffA[0] = 'a'; item.cchTextMax = sizeof(buffA); r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); expect(1, r); ok(!memcmp(item.pszText, text, sizeof(text)), "got %s, expected %s\n", item.pszText, text); }
/* Query param from subitem: returns main item param */ memset (&item, 0xcc, sizeof (item)); item.mask = LVIF_PARAM; item.iItem = 0; item.iSubItem = 1; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); expect(1, r); ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest);
/* Set up param on first subitem: no effect */ memset (&item, 0xcc, sizeof (item)); item.mask = LVIF_PARAM; item.iItem = 0; item.iSubItem = 1; item.lParam = lparamTest+1; r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM) &item); expect(0, r);
/* Query param from subitem again: should still return main item param */ memset (&item, 0xcc, sizeof (item)); item.mask = LVIF_PARAM; item.iItem = 0; item.iSubItem = 1; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); expect(1, r); ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest);
/**** Some tests of state highlighting ****/ memset (&item, 0xcc, sizeof (item)); item.mask = LVIF_STATE; item.iItem = 0; item.iSubItem = 0; item.state = LVIS_SELECTED; item.stateMask = LVIS_SELECTED | LVIS_DROPHILITED; r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM) &item); expect(1, r); item.iSubItem = 1; item.state = LVIS_DROPHILITED; r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM) &item); expect(1, r);
memset (&item, 0xcc, sizeof (item)); item.mask = LVIF_STATE; item.iItem = 0; item.iSubItem = 0; item.stateMask = -1; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); expect(1, r); ok(item.state == LVIS_SELECTED, "got state %x, expected %x\n", item.state, LVIS_SELECTED); item.iSubItem = 1; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); expect(1, r); todo_wine ok(item.state == LVIS_DROPHILITED, "got state %x, expected %x\n", item.state, LVIS_DROPHILITED);
/* some notnull but meaningless masks */ memset (&item, 0, sizeof(item)); item.mask = LVIF_NORECOMPUTE; item.iItem = 0; item.iSubItem = 0; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); expect(1, r); memset (&item, 0, sizeof(item)); item.mask = LVIF_DI_SETITEM; item.iItem = 0; item.iSubItem = 0; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); expect(1, r);
/* set text to callback value already having it */ r = SendMessageA(hwnd, LVM_DELETEALLITEMS, 0, 0); expect(TRUE, r); memset (&item, 0, sizeof (item)); item.mask = LVIF_TEXT; item.pszText = LPSTR_TEXTCALLBACKA; item.iItem = 0; r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); expect(0, r); memset (&item, 0, sizeof (item));
flush_sequences(sequences, NUM_MSG_SEQUENCES);
item.pszText = LPSTR_TEXTCALLBACKA; r = SendMessageA(hwnd, LVM_SETITEMTEXTA, 0 , (LPARAM) &item); expect(TRUE, r);
ok_sequence(sequences, PARENT_SEQ_INDEX, textcallback_set_again_parent_seq, "check callback text comparison rule", FALSE);
DestroyWindow(hwnd);}
static void test_columns(void){ HWND hwnd, header; LVCOLUMNA column; LVITEMA item; INT order[2]; CHAR buff[5]; DWORD rc;
hwnd = CreateWindowExA(0, WC_LISTVIEWA, "foo", LVS_LIST, 10, 10, 100, 200, hwndparent, NULL, NULL, NULL); ok(hwnd != NULL, "failed to create listview window\n");
header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); ok(header == NULL, "got %p\n", header);
rc = SendMessageA(hwnd, LVM_GETCOLUMNORDERARRAY, 2, (LPARAM)&order); ok(rc == 0, "got %d\n", rc);
header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); ok(header == NULL, "got %p\n", header);
DestroyWindow(hwnd);
hwnd = CreateWindowExA(0, WC_LISTVIEWA, "foo", LVS_REPORT, 10, 10, 100, 200, hwndparent, NULL, NULL, NULL); ok(hwnd != NULL, "failed to create listview window\n");
rc = SendMessageA(hwnd, LVM_DELETECOLUMN, -1, 0); ok(!rc, "got %d\n", rc);
rc = SendMessageA(hwnd, LVM_DELETECOLUMN, 0, 0); ok(!rc, "got %d\n", rc);
/* Add a column with no mask */ memset(&column, 0xcc, sizeof(column)); column.mask = 0; rc = SendMessageA(hwnd, LVM_INSERTCOLUMNA, 0, (LPARAM)&column); ok(rc == 0, "Inserting column with no mask failed with %d\n", rc);
/* Check its width */ rc = SendMessageA(hwnd, LVM_GETCOLUMNWIDTH, 0, 0); ok(rc == 10, "Inserting column with no mask failed to set width to 10 with %d\n", rc);
DestroyWindow(hwnd);
/* LVM_GETCOLUMNORDERARRAY */ hwnd = create_listview_control(LVS_REPORT); subclass_header(hwnd);
memset(&column, 0, sizeof(column)); column.mask = LVCF_WIDTH; column.cx = 100; rc = SendMessageA(hwnd, LVM_INSERTCOLUMNA, 0, (LPARAM)&column); expect(0, rc);
column.cx = 200; rc = SendMessageA(hwnd, LVM_INSERTCOLUMNA, 1, (LPARAM)&column); expect(1, rc);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
rc = SendMessageA(hwnd, LVM_GETCOLUMNORDERARRAY, 2, (LPARAM)&order); expect(1, rc); ok(order[0] == 0, "Expected order 0, got %d\n", order[0]); ok(order[1] == 1, "Expected order 1, got %d\n", order[1]);
rc = SendMessageA(hwnd, LVM_GETCOLUMNORDERARRAY, 0, 0); expect(0, rc);
ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_getorderarray_seq, "get order array", FALSE);
/* LVM_SETCOLUMNORDERARRAY */ flush_sequences(sequences, NUM_MSG_SEQUENCES);
order[0] = 0; order[1] = 1; rc = SendMessageA(hwnd, LVM_SETCOLUMNORDERARRAY, 2, (LPARAM)&order); expect(1, rc);
rc = SendMessageA(hwnd, LVM_SETCOLUMNORDERARRAY, 0, 0); expect(0, rc);
ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_setorderarray_seq, "set order array", FALSE);
/* after column added subitem is considered as present */ insert_item(hwnd, 0);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
item.pszText = buff; item.cchTextMax = sizeof(buff); item.iItem = 0; item.iSubItem = 1; item.mask = LVIF_TEXT; memset(&g_itema, 0, sizeof(g_itema)); rc = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item); expect(1, rc); ok(g_itema.iSubItem == 1, "got %d\n", g_itema.iSubItem);
ok_sequence(sequences, PARENT_SEQ_INDEX, single_getdispinfo_parent_seq, "get subitem text after column added", FALSE);
DestroyWindow(hwnd);
/* Columns are not created right away. */ hwnd = create_listview_control(LVS_REPORT); ok(hwnd != NULL, "Failed to create a listview window.\n");
insert_item(hwnd, 0);
header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); ok(IsWindow(header), "Expected header handle.\n"); rc = SendMessageA(header, HDM_GETITEMCOUNT, 0, 0); ok(!rc, "Unexpected column count.\n");
DestroyWindow(hwnd);}
/* test setting imagelist between WM_NCCREATE and WM_CREATE */static WNDPROC listviewWndProc;static HIMAGELIST test_create_imagelist;
static LRESULT CALLBACK create_test_wndproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){ LRESULT ret;
if (uMsg == WM_CREATE) { CREATESTRUCTA *lpcs = (CREATESTRUCTA*)lParam; lpcs->style |= LVS_REPORT; } ret = CallWindowProcA(listviewWndProc, hwnd, uMsg, wParam, lParam); if (uMsg == WM_CREATE) SendMessageA(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)test_create_imagelist); return ret;}
/* Header creation is delayed in classic implementation. */#define TEST_NO_HEADER(a) test_header_presence_(a, FALSE, __LINE__)#define TEST_HEADER_EXPECTED(a) test_header_presence_(a, TRUE, __LINE__)#define TEST_NO_HEADER2(a, b) test_header_presence_(a, b, __LINE__)static void test_header_presence_(HWND hwnd, BOOL present, int line){ HWND header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
if (present) { ok_(__FILE__, line)(IsWindow(header), "Header should have been created.\n"); if (header) /* FIXME: remove when todo's are fixed */ ok_(__FILE__, line)(header == GetDlgItem(hwnd, 0), "Dialog item expected.\n"); } else { ok_(__FILE__, line)(!IsWindow(header), "Header shouldn't be created.\n"); ok_(__FILE__, line)(NULL == GetDlgItem(hwnd, 0), "NULL dialog item expected.\n"); }}
static void test_create(BOOL is_version_6){ static const WCHAR testtextW[] = {'t','e','s','t',' ','t','e','x','t',0}; char buff[16]; HWND hList; HWND hHeader; LONG_PTR ret; LONG r; LVCOLUMNA col; RECT rect; WNDCLASSEXA cls; DWORD style; ATOM class;
if (is_win_xp() && is_version_6) { win_skip("Skipping some tests on XP.\n"); return; }
cls.cbSize = sizeof(WNDCLASSEXA); r = GetClassInfoExA(GetModuleHandleA(NULL), WC_LISTVIEWA, &cls); ok(r, "Failed to get class info.\n"); listviewWndProc = cls.lpfnWndProc; cls.lpfnWndProc = create_test_wndproc; cls.lpszClassName = "MyListView32"; class = RegisterClassExA(&cls); ok(class, "Failed to register class.\n");
test_create_imagelist = pImageList_Create(16, 16, 0, 5, 10); hList = CreateWindowA("MyListView32", "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL, GetModuleHandleA(NULL), 0); ok((HIMAGELIST)SendMessageA(hList, LVM_GETIMAGELIST, 0, 0) == test_create_imagelist, "Image list not obtained\n"); hHeader = (HWND)SendMessageA(hList, LVM_GETHEADER, 0, 0); ok(IsWindow(hHeader) && IsWindowVisible(hHeader), "Listview not in report mode\n"); ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n"); DestroyWindow(hList);
/* header isn't created on LVS_ICON and LVS_LIST styles */ hList = CreateWindowA(WC_LISTVIEWA, "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL, GetModuleHandleA(NULL), 0); TEST_NO_HEADER(hList);
/* insert column */ memset(&col, 0, sizeof(LVCOLUMNA)); col.mask = LVCF_WIDTH; col.cx = 100; r = SendMessageA(hList, LVM_INSERTCOLUMNA, 0, (LPARAM)&col); expect(0, r); TEST_HEADER_EXPECTED(hList); hHeader = (HWND)SendMessageA(hList, LVM_GETHEADER, 0, 0); style = GetWindowLongA(hHeader, GWL_STYLE); ok(!(style & HDS_HIDDEN), "Not expected HDS_HIDDEN\n"); DestroyWindow(hList);
hList = CreateWindowA(WC_LISTVIEWA, "Test", WS_VISIBLE|LVS_LIST, 0, 0, 100, 100, NULL, NULL, GetModuleHandleA(NULL), 0); TEST_NO_HEADER(hList); /* insert column */ memset(&col, 0, sizeof(LVCOLUMNA)); col.mask = LVCF_WIDTH; col.cx = 100; r = SendMessageA(hList, LVM_INSERTCOLUMNA, 0, (LPARAM)&col); expect(0, r); TEST_HEADER_EXPECTED(hList); DestroyWindow(hList);
/* try to switch LVS_ICON -> LVS_REPORT and back LVS_ICON -> LVS_REPORT */ hList = CreateWindowA(WC_LISTVIEWA, "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL, GetModuleHandleA(NULL), 0); ret = SetWindowLongPtrA(hList, GWL_STYLE, GetWindowLongPtrA(hList, GWL_STYLE) | LVS_REPORT); ok(ret & WS_VISIBLE, "Style wrong, should have WS_VISIBLE\n"); TEST_HEADER_EXPECTED(hList); ret = SetWindowLongPtrA(hList, GWL_STYLE, GetWindowLongA(hList, GWL_STYLE) & ~LVS_REPORT); ok((ret & WS_VISIBLE) && (ret & LVS_REPORT), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n"); TEST_HEADER_EXPECTED(hList); DestroyWindow(hList);
/* try to switch LVS_LIST -> LVS_REPORT and back LVS_LIST -> LVS_REPORT */ hList = CreateWindowA(WC_LISTVIEWA, "Test", WS_VISIBLE|LVS_LIST, 0, 0, 100, 100, NULL, NULL, GetModuleHandleA(NULL), 0); ret = SetWindowLongPtrA(hList, GWL_STYLE, (GetWindowLongPtrA(hList, GWL_STYLE) & ~LVS_LIST) | LVS_REPORT); ok(((ret & WS_VISIBLE) && (ret & LVS_LIST)), "Style wrong, should have WS_VISIBLE|LVS_LIST\n"); TEST_HEADER_EXPECTED(hList); ret = SetWindowLongPtrA(hList, GWL_STYLE, (GetWindowLongPtrA(hList, GWL_STYLE) & ~LVS_REPORT) | LVS_LIST); ok(((ret & WS_VISIBLE) && (ret & LVS_REPORT)), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n"); TEST_HEADER_EXPECTED(hList); DestroyWindow(hList);
/* LVS_REPORT without WS_VISIBLE */ hList = CreateWindowA(WC_LISTVIEWA, "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL, GetModuleHandleA(NULL), 0); hHeader = (HWND)SendMessageA(hList, LVM_GETHEADER, 0, 0);todo_wine_if(is_version_6) TEST_NO_HEADER2(hList, is_version_6);
/* insert column */ memset(&col, 0, sizeof(LVCOLUMNA)); col.mask = LVCF_WIDTH; col.cx = 100; r = SendMessageA(hList, LVM_INSERTCOLUMNA, 0, (LPARAM)&col); expect(0, r); TEST_HEADER_EXPECTED(hList); DestroyWindow(hList);
/* LVS_REPORT without WS_VISIBLE, try to show it */ hList = CreateWindowA(WC_LISTVIEWA, "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL, GetModuleHandleA(NULL), 0);todo_wine_if(is_version_6) TEST_NO_HEADER2(hList, is_version_6);
ShowWindow(hList, SW_SHOW); TEST_HEADER_EXPECTED(hList); DestroyWindow(hList);
/* LVS_REPORT with LVS_NOCOLUMNHEADER */ hList = CreateWindowA(WC_LISTVIEWA, "Test", LVS_REPORT|LVS_NOCOLUMNHEADER|WS_VISIBLE, 0, 0, 100, 100, NULL, NULL, GetModuleHandleA(NULL), 0); TEST_HEADER_EXPECTED(hList); hHeader = (HWND)SendMessageA(hList, LVM_GETHEADER, 0, 0); /* HDS_DRAGDROP set by default */ ok(GetWindowLongPtrA(hHeader, GWL_STYLE) & HDS_DRAGDROP, "Expected header to have HDS_DRAGDROP\n"); DestroyWindow(hList);
/* setting LVS_EX_HEADERDRAGDROP creates header */ hList = CreateWindowA(WC_LISTVIEWA, "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL, GetModuleHandleA(NULL), 0);todo_wine_if(is_version_6) TEST_NO_HEADER2(hList, is_version_6);
SendMessageA(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_HEADERDRAGDROP); TEST_HEADER_EXPECTED(hList); DestroyWindow(hList);
/* setting LVS_EX_GRIDLINES creates header */ hList = CreateWindowA(WC_LISTVIEWA, "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL, GetModuleHandleA(NULL), 0);todo_wine_if(is_version_6) TEST_NO_HEADER2(hList, is_version_6);
SendMessageA(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_GRIDLINES); TEST_HEADER_EXPECTED(hList); DestroyWindow(hList);
/* setting LVS_EX_FULLROWSELECT creates header */ hList = CreateWindowA(WC_LISTVIEWA, "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL, GetModuleHandleA(NULL), 0);todo_wine_if(is_version_6) TEST_NO_HEADER2(hList, is_version_6); SendMessageA(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT); TEST_HEADER_EXPECTED(hList); DestroyWindow(hList);
/* not report style accepts LVS_EX_HEADERDRAGDROP too */ hList = create_listview_control(LVS_ICON); SendMessageA(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_HEADERDRAGDROP); r = SendMessageA(hList, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0); ok(r & LVS_EX_HEADERDRAGDROP, "Expected LVS_EX_HEADERDRAGDROP to be set\n"); DestroyWindow(hList);
/* requesting header info with LVM_GETSUBITEMRECT doesn't create it */ hList = CreateWindowA(WC_LISTVIEWA, "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL, GetModuleHandleA(NULL), 0);todo_wine_if(is_version_6) TEST_NO_HEADER2(hList, is_version_6);
SetRect(&rect, LVIR_BOUNDS, 1, -10, -10); r = SendMessageA(hList, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect); ok(r == 1, "Unexpected ret value %d.\n", r); /* right value contains garbage, probably because header columns are not set up */ ok(rect.bottom >= 0, "Unexpected rectangle.\n");
todo_wine_if(is_version_6) TEST_NO_HEADER2(hList, is_version_6); DestroyWindow(hList);
/* WM_MEASUREITEM should be sent when created with LVS_OWNERDRAWFIXED */ flush_sequences(sequences, NUM_MSG_SEQUENCES); hList = create_listview_control(LVS_OWNERDRAWFIXED | LVS_REPORT); ok_sequence(sequences, PARENT_SEQ_INDEX, create_ownerdrawfixed_parent_seq, "created with LVS_OWNERDRAWFIXED|LVS_REPORT - parent seq", FALSE); DestroyWindow(hList);
/* Test that window text is preserved. */ hList = CreateWindowExA(0, WC_LISTVIEWA, "test text", WS_CHILD | WS_BORDER | WS_VISIBLE, 0, 0, 100, 100, hwndparent, NULL, GetModuleHandleA(NULL), NULL); ok(hList != NULL, "Failed to create ListView window.\n"); *buff = 0; GetWindowTextA(hList, buff, sizeof(buff)); ok(!strcmp(buff, "test text"), "Unexpected window text %s.\n", buff); DestroyWindow(hList);
hList = CreateWindowExW(0, WC_LISTVIEWW, testtextW, WS_CHILD | WS_BORDER | WS_VISIBLE, 0, 0, 100, 100, hwndparent, NULL, GetModuleHandleA(NULL), NULL); ok(hList != NULL, "Failed to create ListView window.\n"); *buff = 0; GetWindowTextA(hList, buff, sizeof(buff)); ok(!strcmp(buff, "test text"), "Unexpected window text %s.\n", buff); DestroyWindow(hList);
r = UnregisterClassA("MyListView32", NULL); ok(r, "Failed to unregister test class.\n");}
static void test_redraw(void){ HWND hwnd; HDC hdc; BOOL res; DWORD r; RECT rect;
hwnd = create_listview_control(LVS_REPORT); subclass_header(hwnd);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
InvalidateRect(hwnd, NULL, TRUE); UpdateWindow(hwnd); ok_sequence(sequences, LISTVIEW_SEQ_INDEX, redraw_listview_seq, "redraw listview", FALSE);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
/* forward WM_ERASEBKGND to parent on CLR_NONE background color */ /* 1. Without backbuffer */ res = SendMessageA(hwnd, LVM_SETBKCOLOR, 0, CLR_NONE); expect(TRUE, res);
hdc = GetWindowDC(hwndparent);
flush_sequences(sequences, NUM_MSG_SEQUENCES); r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0); ok(r == 1, "Expected not zero result\n"); ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, forward_erasebkgnd_parent_seq, "forward WM_ERASEBKGND on CLR_NONE", FALSE);
res = SendMessageA(hwnd, LVM_SETBKCOLOR, 0, CLR_DEFAULT); expect(TRUE, res);
flush_sequences(sequences, NUM_MSG_SEQUENCES); r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0); expect(1, r); ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, empty_seq, "don't forward WM_ERASEBKGND on non-CLR_NONE", FALSE);
/* 2. With backbuffer */ SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_DOUBLEBUFFER, LVS_EX_DOUBLEBUFFER); res = SendMessageA(hwnd, LVM_SETBKCOLOR, 0, CLR_NONE); expect(TRUE, res);
flush_sequences(sequences, NUM_MSG_SEQUENCES); r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0); expect(1, r); ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, forward_erasebkgnd_parent_seq, "forward WM_ERASEBKGND on CLR_NONE", FALSE);
res = SendMessageA(hwnd, LVM_SETBKCOLOR, 0, CLR_DEFAULT); expect(TRUE, res);
flush_sequences(sequences, NUM_MSG_SEQUENCES); r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0); todo_wine expect(1, r); ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, empty_seq, "don't forward WM_ERASEBKGND on non-CLR_NONE", FALSE);
ReleaseDC(hwndparent, hdc);
/* test setting the window style to what it already was */ UpdateWindow(hwnd); SetWindowLongA(hwnd, GWL_STYLE, GetWindowLongA(hwnd, GWL_STYLE)); GetUpdateRect(hwnd, &rect, FALSE); ok(rect.left == 0 && rect.top == 0 && rect.right == 0 && rect.bottom == 0, "Expected empty update rect, got %s\n", wine_dbgstr_rect(&rect));
DestroyWindow(hwnd);}
static LRESULT WINAPI cd_wndproc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ COLORREF clr, c0ffee = RGB(0xc0, 0xff, 0xee);
if(message == WM_NOTIFY) { NMHDR *nmhdr = (NMHDR*)lParam; if(nmhdr->code == NM_CUSTOMDRAW) { NMLVCUSTOMDRAW *nmlvcd = (NMLVCUSTOMDRAW*)nmhdr; BOOL showsel_always = !!(GetWindowLongA(nmlvcd->nmcd.hdr.hwndFrom, GWL_STYLE) & LVS_SHOWSELALWAYS); BOOL is_selected = !!(nmlvcd->nmcd.uItemState & CDIS_SELECTED); struct message msg;
msg.message = message; msg.flags = sent|wparam|lparam|custdraw; msg.wParam = wParam; msg.lParam = lParam; msg.id = nmhdr->code; msg.stage = nmlvcd->nmcd.dwDrawStage; add_message(sequences, PARENT_CD_SEQ_INDEX, &msg);
switch(nmlvcd->nmcd.dwDrawStage) { case CDDS_PREPAINT: SetBkColor(nmlvcd->nmcd.hdc, c0ffee); return CDRF_NOTIFYITEMDRAW|CDRF_NOTIFYPOSTPAINT; case CDDS_ITEMPREPAINT: clr = GetBkColor(nmlvcd->nmcd.hdc); todo_wine_if(nmlvcd->iSubItem) ok(clr == c0ffee, "Unexpected background color %#x.\n", clr); nmlvcd->clrTextBk = CLR_DEFAULT; nmlvcd->clrText = RGB(0, 255, 0); return CDRF_NOTIFYSUBITEMDRAW|CDRF_NOTIFYPOSTPAINT; case CDDS_ITEMPREPAINT | CDDS_SUBITEM: clr = GetBkColor(nmlvcd->nmcd.hdc); todo_wine_if(showsel_always && is_selected && nmlvcd->iSubItem) { ok(nmlvcd->clrTextBk == CLR_DEFAULT, "Unexpected text background %#x.\n", nmlvcd->clrTextBk); ok(nmlvcd->clrText == RGB(0, 255, 0), "Unexpected text color %#x.\n", nmlvcd->clrText); } if (showsel_always && is_selected && nmlvcd->iSubItem) ok(clr == GetSysColor(COLOR_3DFACE), "Unexpected background color %#x.\n", clr); else todo_wine_if(nmlvcd->iSubItem) ok(clr == c0ffee, "clr=%.8x\n", clr); return CDRF_NOTIFYPOSTPAINT; case CDDS_ITEMPOSTPAINT | CDDS_SUBITEM: clr = GetBkColor(nmlvcd->nmcd.hdc); if (showsel_always && is_selected) ok(clr == GetSysColor(COLOR_3DFACE), "Unexpected background color %#x.\n", clr); else { todo_wine ok(clr == c0ffee, "Unexpected background color %#x.\n", clr); }
todo_wine_if(showsel_always) { ok(nmlvcd->clrTextBk == CLR_DEFAULT, "Unexpected text background color %#x.\n", nmlvcd->clrTextBk); ok(nmlvcd->clrText == RGB(0, 255, 0), "got 0x%x\n", nmlvcd->clrText); } return CDRF_DODEFAULT; } return CDRF_DODEFAULT; } }
return DefWindowProcA(hwnd, message, wParam, lParam);}
static void test_customdraw(void){ HWND hwnd; WNDPROC oldwndproc; LVITEMA item;
hwnd = create_listview_control(LVS_REPORT);
insert_column(hwnd, 0); insert_column(hwnd, 1); insert_item(hwnd, 0);
oldwndproc = (WNDPROC)SetWindowLongPtrA(hwndparent, GWLP_WNDPROC, (LONG_PTR)cd_wndproc);
InvalidateRect(hwnd, NULL, TRUE); UpdateWindow(hwnd);
/* message tests */ flush_sequences(sequences, NUM_MSG_SEQUENCES); InvalidateRect(hwnd, NULL, TRUE); UpdateWindow(hwnd); ok_sequence(sequences, PARENT_CD_SEQ_INDEX, parent_report_cd_seq, "parent customdraw, LVS_REPORT", FALSE);
/* Check colors when item is selected. */ item.mask = LVIF_STATE; item.stateMask = LVIS_SELECTED; item.state = LVIS_SELECTED; SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
flush_sequences(sequences, NUM_MSG_SEQUENCES); InvalidateRect(hwnd, NULL, TRUE); UpdateWindow(hwnd); ok_sequence(sequences, PARENT_CD_SEQ_INDEX, parent_report_cd_seq, "parent customdraw, item selected, LVS_REPORT, selection", FALSE);
SetWindowLongW(hwnd, GWL_STYLE, GetWindowLongW(hwnd, GWL_STYLE) | LVS_SHOWSELALWAYS); flush_sequences(sequences, NUM_MSG_SEQUENCES); InvalidateRect(hwnd, NULL, TRUE); UpdateWindow(hwnd); ok_sequence(sequences, PARENT_CD_SEQ_INDEX, parent_report_cd_seq, "parent customdraw, item selected, LVS_SHOWSELALWAYS, LVS_REPORT", FALSE);
DestroyWindow(hwnd);
hwnd = create_listview_control(LVS_LIST);
insert_column(hwnd, 0); insert_column(hwnd, 1); insert_item(hwnd, 0);
flush_sequences(sequences, NUM_MSG_SEQUENCES); InvalidateRect(hwnd, NULL, TRUE); UpdateWindow(hwnd); ok_sequence(sequences, PARENT_CD_SEQ_INDEX, parent_list_cd_seq, "parent customdraw, LVS_LIST", FALSE);
SetWindowLongPtrA(hwndparent, GWLP_WNDPROC, (LONG_PTR)oldwndproc); DestroyWindow(hwnd);}
static void test_icon_spacing(void){ /* LVM_SETICONSPACING */ /* note: LVM_SETICONSPACING returns the previous icon spacing if successful */
HWND hwnd; WORD w, h; INT r;
hwnd = create_listview_control(LVS_ICON); ok(hwnd != NULL, "failed to create a listview window\n");
r = SendMessageA(hwnd, WM_NOTIFYFORMAT, (WPARAM)hwndparent, NF_REQUERY); expect(NFR_ANSI, r);
/* reset the icon spacing to defaults */ SendMessageA(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(-1, -1));
/* now we can request what the defaults are */ r = SendMessageA(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(-1, -1)); w = LOWORD(r); h = HIWORD(r);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
r = SendMessageA(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(20, 30)); ok(r == MAKELONG(w, h) || broken(r == MAKELONG(w, w)), /* win98 */ "Expected %d, got %d\n", MAKELONG(w, h), r);
r = SendMessageA(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(25, 35)); expect(MAKELONG(20,30), r);
r = SendMessageA(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(-1,-1)); expect(MAKELONG(25,35), r);
ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_icon_spacing_seq, "test icon spacing seq", FALSE);
flush_sequences(sequences, NUM_MSG_SEQUENCES); DestroyWindow(hwnd);}
static void test_color(void){ RECT rect; HWND hwnd; DWORD r; int i;
COLORREF color; COLORREF colors[4] = {RGB(0,0,0), RGB(100,50,200), CLR_NONE, RGB(255,255,255)};
hwnd = create_listview_control(LVS_REPORT); ok(hwnd != NULL, "failed to create a listview window\n");
flush_sequences(sequences, NUM_MSG_SEQUENCES);
for (i = 0; i < 4; i++) { color = colors[i];
r = SendMessageA(hwnd, LVM_SETBKCOLOR, 0, color); expect(TRUE, r); r = SendMessageA(hwnd, LVM_GETBKCOLOR, 0, 0); expect(color, r);
r = SendMessageA(hwnd, LVM_SETTEXTCOLOR, 0, color); expect (TRUE, r); r = SendMessageA(hwnd, LVM_GETTEXTCOLOR, 0, 0); expect(color, r);
r = SendMessageA(hwnd, LVM_SETTEXTBKCOLOR, 0, color); expect(TRUE, r); r = SendMessageA(hwnd, LVM_GETTEXTBKCOLOR, 0, 0); expect(color, r); }
ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_color_seq, "test color seq", FALSE); flush_sequences(sequences, NUM_MSG_SEQUENCES);
/* invalidation test done separately to avoid a message chain mess */ r = ValidateRect(hwnd, NULL); expect(TRUE, r); r = SendMessageA(hwnd, LVM_SETBKCOLOR, 0, colors[0]); expect(TRUE, r);
rect.right = rect.bottom = 1; r = GetUpdateRect(hwnd, &rect, TRUE); todo_wine expect(FALSE, r); ok(rect.right == 0 && rect.bottom == 0, "got update rectangle\n");
r = ValidateRect(hwnd, NULL); expect(TRUE, r); r = SendMessageA(hwnd, LVM_SETTEXTCOLOR, 0, colors[0]); expect(TRUE, r);
rect.right = rect.bottom = 1; r = GetUpdateRect(hwnd, &rect, TRUE); todo_wine expect(FALSE, r); ok(rect.right == 0 && rect.bottom == 0, "got update rectangle\n");
r = ValidateRect(hwnd, NULL); expect(TRUE, r); r = SendMessageA(hwnd, LVM_SETTEXTBKCOLOR, 0, colors[0]); expect(TRUE, r);
rect.right = rect.bottom = 1; r = GetUpdateRect(hwnd, &rect, TRUE); todo_wine expect(FALSE, r); ok(rect.right == 0 && rect.bottom == 0, "got update rectangle\n");
DestroyWindow(hwnd);}
static void test_item_count(void){ /* LVM_INSERTITEM, LVM_DELETEITEM, LVM_DELETEALLITEMS, LVM_GETITEMCOUNT */
HWND hwnd; DWORD r; HDC hdc; HFONT hOldFont; TEXTMETRICA tm; RECT rect; INT height;
LVITEMA item0; LVITEMA item1; LVITEMA item2; static CHAR item0text[] = "item0"; static CHAR item1text[] = "item1"; static CHAR item2text[] = "item2";
hwnd = create_listview_control(LVS_REPORT); ok(hwnd != NULL, "failed to create a listview window\n");
/* resize in dpiaware manner to fit all 3 items added */ hdc = GetDC(0); hOldFont = SelectObject(hdc, GetStockObject(SYSTEM_FONT)); GetTextMetricsA(hdc, &tm); /* 2 extra pixels for bounds and header border */ height = tm.tmHeight + 2; SelectObject(hdc, hOldFont); ReleaseDC(0, hdc);
GetWindowRect(hwnd, &rect); /* 3 items + 1 header + 1 to be sure */ MoveWindow(hwnd, 0, 0, rect.right - rect.left, 5 * height, FALSE);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
r = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0); expect(0, r);
/* [item0] */ item0.mask = LVIF_TEXT; item0.iItem = 0; item0.iSubItem = 0; item0.pszText = item0text; r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item0); expect(0, r);
/* [item0, item1] */ item1.mask = LVIF_TEXT; item1.iItem = 1; item1.iSubItem = 0; item1.pszText = item1text; r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item1); expect(1, r);
/* [item0, item1, item2] */ item2.mask = LVIF_TEXT; item2.iItem = 2; item2.iSubItem = 0; item2.pszText = item2text; r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item2); expect(2, r);
r = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0); expect(3, r);
/* [item0, item1] */ r = SendMessageA(hwnd, LVM_DELETEITEM, 2, 0); expect(TRUE, r);
r = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0); expect(2, r);
/* [] */ r = SendMessageA(hwnd, LVM_DELETEALLITEMS, 0, 0); expect(TRUE, r);
r = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0); expect(0, r);
/* [item0] */ r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item1); expect(0, r);
/* [item0, item1] */ r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item1); expect(1, r);
r = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0); expect(2, r);
/* [item0, item1, item2] */ r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item2); expect(2, r);
r = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0); expect(3, r);
ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_item_count_seq, "test item count seq", FALSE);
flush_sequences(sequences, NUM_MSG_SEQUENCES); DestroyWindow(hwnd);}
static void test_item_position(void){ /* LVM_SETITEMPOSITION/LVM_GETITEMPOSITION */
HWND hwnd; DWORD r; POINT position;
LVITEMA item0; LVITEMA item1; LVITEMA item2; static CHAR item0text[] = "item0"; static CHAR item1text[] = "item1"; static CHAR item2text[] = "item2";
hwnd = create_listview_control(LVS_ICON); ok(hwnd != NULL, "failed to create a listview window\n");
flush_sequences(sequences, NUM_MSG_SEQUENCES);
/* [item0] */ item0.mask = LVIF_TEXT; item0.iItem = 0; item0.iSubItem = 0; item0.pszText = item0text; r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item0); expect(0, r);
/* [item0, item1] */ item1.mask = LVIF_TEXT; item1.iItem = 1; item1.iSubItem = 0; item1.pszText = item1text; r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item1); expect(1, r);
/* [item0, item1, item2] */ item2.mask = LVIF_TEXT; item2.iItem = 2; item2.iSubItem = 0; item2.pszText = item2text; r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item2); expect(2, r);
r = SendMessageA(hwnd, LVM_SETITEMPOSITION, 1, MAKELPARAM(10,5)); expect(TRUE, r); r = SendMessageA(hwnd, LVM_GETITEMPOSITION, 1, (LPARAM) &position); expect(TRUE, r); expect2(10, 5, position.x, position.y);
r = SendMessageA(hwnd, LVM_SETITEMPOSITION, 2, MAKELPARAM(0,0)); expect(TRUE, r); r = SendMessageA(hwnd, LVM_GETITEMPOSITION, 2, (LPARAM) &position); expect(TRUE, r); expect2(0, 0, position.x, position.y);
r = SendMessageA(hwnd, LVM_SETITEMPOSITION, 0, MAKELPARAM(20,20)); expect(TRUE, r); r = SendMessageA(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM) &position); expect(TRUE, r); expect2(20, 20, position.x, position.y);
ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_itempos_seq, "test item position seq", TRUE);
flush_sequences(sequences, NUM_MSG_SEQUENCES); DestroyWindow(hwnd);}
static void test_getorigin(void){ /* LVM_GETORIGIN */
HWND hwnd; DWORD r; POINT position;
position.x = position.y = 0;
hwnd = create_listview_control(LVS_ICON); ok(hwnd != NULL, "failed to create a listview window\n"); flush_sequences(sequences, NUM_MSG_SEQUENCES);
r = SendMessageA(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position); expect(TRUE, r); flush_sequences(sequences, NUM_MSG_SEQUENCES); DestroyWindow(hwnd);
hwnd = create_listview_control(LVS_SMALLICON); ok(hwnd != NULL, "failed to create a listview window\n"); flush_sequences(sequences, NUM_MSG_SEQUENCES);
r = SendMessageA(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position); expect(TRUE, r); flush_sequences(sequences, NUM_MSG_SEQUENCES); DestroyWindow(hwnd);
hwnd = create_listview_control(LVS_LIST); ok(hwnd != NULL, "failed to create a listview window\n"); flush_sequences(sequences, NUM_MSG_SEQUENCES);
r = SendMessageA(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position); expect(FALSE, r); flush_sequences(sequences, NUM_MSG_SEQUENCES); DestroyWindow(hwnd);
hwnd = create_listview_control(LVS_REPORT); ok(hwnd != NULL, "failed to create a listview window\n"); flush_sequences(sequences, NUM_MSG_SEQUENCES);
r = SendMessageA(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position); expect(FALSE, r); flush_sequences(sequences, NUM_MSG_SEQUENCES); DestroyWindow(hwnd);}
static void test_multiselect(void){ typedef struct t_select_task { const char *descr; int initPos; int loopVK; int count; int result; } select_task;
HWND hwnd; INT r; int i, j; static const int items=5; DWORD item_count; BYTE kstate[256]; select_task task; LONG_PTR style; LVITEMA item;
static struct t_select_task task_list[] = { { "using VK_DOWN", 0, VK_DOWN, -1, -1 }, { "using VK_UP", -1, VK_UP, -1, -1 }, { "using VK_END", 0, VK_END, 1, -1 }, { "using VK_HOME", -1, VK_HOME, 1, -1 } };
hwnd = create_listview_control(LVS_REPORT);
for (i = 0; i < items; i++) insert_item(hwnd, 0);
item_count = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0); expect(items, item_count);
r = SendMessageA(hwnd, LVM_SETSELECTIONMARK, 0, -1); ok(r == -1, "got %d\n", r);
r = SendMessageA(hwnd, LVM_SETSELECTIONMARK, 0, 0); ok(r == -1, "got %d\n", r);
r = SendMessageA(hwnd, LVM_SETSELECTIONMARK, 0, 0); ok(r == 0, "got %d\n", r);
/* out of range index */ r = SendMessageA(hwnd, LVM_SETSELECTIONMARK, 0, items); ok(r == 0, "got %d\n", r);
r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); ok(r == 0, "got %d\n", r);
r = SendMessageA(hwnd, LVM_SETSELECTIONMARK, 0, -2); ok(r == 0, "got %d\n", r);
r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); ok(r == 0, "got %d\n", r);
for (i = 0; i < ARRAY_SIZE(task_list); i++) { DWORD selected_count; LVITEMA item;
task = task_list[i];
/* deselect all items */ item.state = 0; item.stateMask = LVIS_SELECTED; r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); ok(r, "got %d\n", r); SendMessageA(hwnd, LVM_SETSELECTIONMARK, 0, -1);
/* set initial position */ r = SendMessageA(hwnd, LVM_SETSELECTIONMARK, 0, (task.initPos == -1 ? item_count -1 : task.initPos)); ok(r, "got %d\n", r);
item.state = LVIS_SELECTED; item.stateMask = LVIS_SELECTED; r = SendMessageA(hwnd, LVM_SETITEMSTATE, task.initPos == -1 ? item_count-1 : task.initPos, (LPARAM)&item); ok(r, "got %d\n", r);
selected_count = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0); ok(selected_count == 1, "expected 1, got %d\n", selected_count);
/* Set SHIFT key pressed */ GetKeyboardState(kstate); kstate[VK_SHIFT]=0x80; SetKeyboardState(kstate);
for (j=1;j<=(task.count == -1 ? item_count : task.count);j++) { r = SendMessageA(hwnd, WM_KEYDOWN, task.loopVK, 0); expect(0,r); r = SendMessageA(hwnd, WM_KEYUP, task.loopVK, 0); expect(0,r); }
selected_count = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
ok((task.result == -1 ? item_count : task.result) == selected_count, "Failed multiple selection %s. There should be %d selected items (is %d)\n", task.descr, item_count, selected_count);
/* Set SHIFT key released */ GetKeyboardState(kstate); kstate[VK_SHIFT]=0x00; SetKeyboardState(kstate); } DestroyWindow(hwnd);
/* make multiple selection, then switch to LVS_SINGLESEL */ hwnd = create_listview_control(LVS_REPORT); for (i=0;i<items;i++) { insert_item(hwnd, 0); } item_count = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0); expect(items,item_count);
/* try with NULL pointer */ r = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, 0); expect(FALSE, r);
/* select all, check notifications */ item.state = 0; item.stateMask = LVIS_SELECTED; r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); ok(r, "got %d\n", r);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
item.stateMask = LVIS_SELECTED; item.state = LVIS_SELECTED; r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); expect(TRUE, r);
ok_sequence(sequences, PARENT_SEQ_INDEX, change_all_parent_seq, "select all notification", FALSE);
/* select all again (all selected already) */ flush_sequences(sequences, NUM_MSG_SEQUENCES);
memset(&g_nmlistview_changing, 0xcc, sizeof(g_nmlistview_changing));
item.stateMask = LVIS_SELECTED; item.state = LVIS_SELECTED; r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); expect(TRUE, r);
ok(g_nmlistview_changing.uNewState == LVIS_SELECTED, "got 0x%x\n", g_nmlistview_changing.uNewState); ok(g_nmlistview_changing.uOldState == LVIS_SELECTED, "got 0x%x\n", g_nmlistview_changing.uOldState); ok(g_nmlistview_changing.uChanged == LVIF_STATE, "got 0x%x\n", g_nmlistview_changing.uChanged);
ok_sequence(sequences, PARENT_SEQ_INDEX, changing_all_parent_seq, "select all notification 2", FALSE);
/* deselect all items */ flush_sequences(sequences, NUM_MSG_SEQUENCES);
item.state = 0; item.stateMask = LVIS_SELECTED; r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); ok(r, "got %d\n", r);
ok_sequence(sequences, PARENT_SEQ_INDEX, change_all_parent_seq, "deselect all notification", FALSE);
/* deselect all items again */ flush_sequences(sequences, NUM_MSG_SEQUENCES); item.state = 0; item.stateMask = LVIS_SELECTED; SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "deselect all notification 2", FALSE);
/* any non-zero state value does the same */ flush_sequences(sequences, NUM_MSG_SEQUENCES);
memset(&g_nmlistview_changing, 0xcc, sizeof(g_nmlistview_changing));
item.stateMask = LVIS_SELECTED; item.state = LVIS_CUT; r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); expect(TRUE, r);
ok(g_nmlistview_changing.uNewState == 0, "got 0x%x\n", g_nmlistview_changing.uNewState); ok(g_nmlistview_changing.uOldState == 0, "got 0x%x\n", g_nmlistview_changing.uOldState); ok(g_nmlistview_changing.uChanged == LVIF_STATE, "got 0x%x\n", g_nmlistview_changing.uChanged);
ok_sequence(sequences, PARENT_SEQ_INDEX, changing_all_parent_seq, "set state all notification 3", FALSE);
r = SendMessageA(hwnd, LVM_SETSELECTIONMARK, 0, -1); ok(r, "got %d\n", r); for (i = 0; i < 3; i++) { item.state = LVIS_SELECTED; item.stateMask = LVIS_SELECTED; r = SendMessageA(hwnd, LVM_SETITEMSTATE, i, (LPARAM)&item); ok(r, "got %d\n", r); }
r = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0); expect(3, r); r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); expect(-1, r);
style = GetWindowLongPtrA(hwnd, GWL_STYLE); ok(!(style & LVS_SINGLESEL), "LVS_SINGLESEL isn't expected\n"); SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SINGLESEL); /* check that style is accepted */ style = GetWindowLongPtrA(hwnd, GWL_STYLE); ok(style & LVS_SINGLESEL, "LVS_SINGLESEL expected\n");
for (i=0;i<3;i++) { r = SendMessageA(hwnd, LVM_GETITEMSTATE, i, LVIS_SELECTED); ok(r & LVIS_SELECTED, "Expected item %d to be selected\n", i); } r = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0); expect(3, r); r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); ok(r == -1, "got %d\n", r);
/* select one more */ item.state = LVIS_SELECTED; item.stateMask = LVIS_SELECTED; r = SendMessageA(hwnd, LVM_SETITEMSTATE, 3, (LPARAM)&item); ok(r, "got %d\n", r);
for (i=0;i<3;i++) { r = SendMessageA(hwnd, LVM_GETITEMSTATE, i, LVIS_SELECTED); ok(!(r & LVIS_SELECTED), "Expected item %d to be unselected\n", i); }
r = SendMessageA(hwnd, LVM_GETITEMSTATE, 3, LVIS_SELECTED); ok(r & LVIS_SELECTED, "Expected item %d to be selected\n", i);
r = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0); expect(1, r); r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); expect(-1, r);
/* try to select all on LVS_SINGLESEL */ memset(&item, 0, sizeof(item)); item.stateMask = LVIS_SELECTED; r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); expect(TRUE, r); r = SendMessageA(hwnd, LVM_SETSELECTIONMARK, 0, -1); ok(r == -1, "got %d\n", r);
item.stateMask = LVIS_SELECTED; item.state = LVIS_SELECTED; r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); expect(FALSE, r);
r = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0); expect(0, r); r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); expect(-1, r);
/* try to deselect all on LVS_SINGLESEL */ item.stateMask = LVIS_SELECTED; item.state = LVIS_SELECTED; r = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item); expect(TRUE, r);
item.stateMask = LVIS_SELECTED; item.state = 0; r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); expect(TRUE, r); r = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0); expect(0, r);
/* 1. selection mark is update when new focused item is set */ style = GetWindowLongPtrA(hwnd, GWL_STYLE); SetWindowLongPtrA(hwnd, GWL_STYLE, style & ~LVS_SINGLESEL);
r = SendMessageA(hwnd, LVM_SETSELECTIONMARK, 0, -1); expect(-1, r);
item.stateMask = LVIS_FOCUSED; item.state = LVIS_FOCUSED; r = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item); expect(TRUE, r);
r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); expect(0, r);
/* it's not updated if already set */ item.stateMask = LVIS_FOCUSED; item.state = LVIS_FOCUSED; r = SendMessageA(hwnd, LVM_SETITEMSTATE, 1, (LPARAM)&item); expect(TRUE, r);
r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); expect(0, r);
r = SendMessageA(hwnd, LVM_SETSELECTIONMARK, 0, -1); expect(0, r);
item.stateMask = LVIS_FOCUSED; item.state = LVIS_FOCUSED; r = SendMessageA(hwnd, LVM_SETITEMSTATE, 1, (LPARAM)&item); expect(TRUE, r);
r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); expect(-1, r);
/* need to reset focused item first */ item.stateMask = LVIS_FOCUSED; item.state = 0; r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); expect(TRUE, r);
item.stateMask = LVIS_FOCUSED; item.state = LVIS_FOCUSED; r = SendMessageA(hwnd, LVM_SETITEMSTATE, 2, (LPARAM)&item); expect(TRUE, r);
r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); expect(2, r);
item.stateMask = LVIS_FOCUSED; item.state = 0; r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); expect(TRUE, r);
r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); expect(2, r);
/* 2. same tests, with LVM_SETITEM */ style = GetWindowLongPtrA(hwnd, GWL_STYLE); SetWindowLongPtrA(hwnd, GWL_STYLE, style & ~LVS_SINGLESEL);
r = SendMessageA(hwnd, LVM_SETSELECTIONMARK, 0, -1); expect(2, r);
item.stateMask = LVIS_FOCUSED; item.state = LVIS_FOCUSED; item.mask = LVIF_STATE; item.iItem = item.iSubItem = 0; r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item); expect(TRUE, r);
r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); expect(0, r);
/* it's not updated if already set */ item.stateMask = LVIS_FOCUSED; item.state = LVIS_FOCUSED; item.mask = LVIF_STATE; item.iItem = 1; item.iSubItem = 0; r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item); expect(TRUE, r);
r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); expect(0, r);
r = SendMessageA(hwnd, LVM_SETSELECTIONMARK, 0, -1); expect(0, r);
item.stateMask = LVIS_FOCUSED; item.state = LVIS_FOCUSED; item.mask = LVIF_STATE; item.iItem = 1; item.iSubItem = 0; r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item); expect(TRUE, r);
r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); expect(-1, r);
/* need to reset focused item first */ item.stateMask = LVIS_FOCUSED; item.state = 0; r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); expect(TRUE, r);
item.stateMask = LVIS_FOCUSED; item.state = LVIS_FOCUSED; item.mask = LVIF_STATE; item.iItem = 2; item.iSubItem = 0; r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item); expect(TRUE, r);
r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); expect(2, r);
item.stateMask = LVIS_FOCUSED; item.state = 0; r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); expect(TRUE, r);
r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); expect(2, r);
DestroyWindow(hwnd);}
static void test_subitem_rect(void){ HWND hwnd; DWORD r; LVCOLUMNA col; RECT rect, rect2; INT arr[3];
/* test LVM_GETSUBITEMRECT for header */ hwnd = create_listview_control(LVS_REPORT); ok(hwnd != NULL, "failed to create a listview window\n"); /* add some columns */ memset(&col, 0, sizeof(LVCOLUMNA)); col.mask = LVCF_WIDTH; col.cx = 100; r = SendMessageA(hwnd, LVM_INSERTCOLUMNA, 0, (LPARAM)&col); expect(0, r); col.cx = 150; r = SendMessageA(hwnd, LVM_INSERTCOLUMNA, 1, (LPARAM)&col); expect(1, r); col.cx = 200; r = SendMessageA(hwnd, LVM_INSERTCOLUMNA, 2, (LPARAM)&col); expect(2, r); /* item = -1 means header, subitem index is 1 based */ SetRect(&rect, LVIR_BOUNDS, 0, 0, 0); r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect); expect(0, r);
SetRect(&rect, LVIR_BOUNDS, 1, 0, 0); r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect); expect(1, r);
expect(100, rect.left); expect(250, rect.right); expect(3, rect.top);
SetRect(&rect, LVIR_BOUNDS, 2, 0, 0); r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect); expect(1, r);
expect(250, rect.left); expect(450, rect.right); expect(3, rect.top);
/* item LVS_REPORT padding isn't applied to subitems */ insert_item(hwnd, 0);
SetRect(&rect, LVIR_BOUNDS, 1, 0, 0); r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect); expect(1, r); expect(100, rect.left); expect(250, rect.right);
SetRect(&rect, LVIR_ICON, 1, 0, 0); r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect); expect(1, r); /* no icon attached - zero width rectangle, with no left padding */ expect(100, rect.left); expect(100, rect.right);
SetRect(&rect, LVIR_LABEL, 1, 0, 0); r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect); expect(1, r); /* same as full LVIR_BOUNDS */ expect(100, rect.left); expect(250, rect.right);
r = SendMessageA(hwnd, LVM_SCROLL, 10, 0); ok(r, "got %d\n", r);
SetRect(&rect, LVIR_BOUNDS, 1, 0, 0); r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect); expect(1, r); expect(90, rect.left); expect(240, rect.right);
SendMessageA(hwnd, LVM_SCROLL, -10, 0);
/* test header interaction */ subclass_header(hwnd); flush_sequences(sequences, NUM_MSG_SEQUENCES);
SetRect(&rect, LVIR_BOUNDS, 1, 0, 0); r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect); expect(1, r);
SetRect(&rect, LVIR_BOUNDS, 1, 0, 0); r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect); expect(1, r);
SetRect(&rect, LVIR_BOUNDS, 1, 0, 0); r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, -10, (LPARAM)&rect); expect(1, r);
SetRect(&rect, LVIR_BOUNDS, 1, 0, 0); r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, 20, (LPARAM)&rect); expect(1, r);
ok_sequence(sequences, LISTVIEW_SEQ_INDEX, getsubitemrect_seq, "LVM_GETSUBITEMRECT negative index", FALSE);
DestroyWindow(hwnd);
/* test subitem rects after re-arranging columns */ hwnd = create_listview_control(LVS_REPORT); ok(hwnd != NULL, "failed to create a listview window\n"); memset(&col, 0, sizeof(LVCOLUMNA)); col.mask = LVCF_WIDTH;
col.cx = 100; r = SendMessageA(hwnd, LVM_INSERTCOLUMNA, 0, (LPARAM)&col); expect(0, r);
col.cx = 200; r = SendMessageA(hwnd, LVM_INSERTCOLUMNA, 1, (LPARAM)&col); expect(1, r);
col.cx = 300; r = SendMessageA(hwnd, LVM_INSERTCOLUMNA, 2, (LPARAM)&col); expect(2, r);
insert_item(hwnd, 0); insert_item(hwnd, 1);
/* wrong item is refused for main item */ SetRect(&rect, LVIR_BOUNDS, 0, -1, -1); r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, 2, (LPARAM)&rect); expect(FALSE, r);
/* for subitems rectangle is calculated even if there's no item added */ SetRect(&rect, LVIR_BOUNDS, 1, -1, -1); r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, 1, (LPARAM)&rect); expect(TRUE, r);
SetRect(&rect2, LVIR_BOUNDS, 1, -1, -1); r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, 2, (LPARAM)&rect2); expect(TRUE, r); expect(rect.right, rect2.right); expect(rect.left, rect2.left); expect(rect.bottom, rect2.top); ok(rect2.bottom > rect2.top, "expected not zero height\n");
arr[0] = 1; arr[1] = 0; arr[2] = 2; r = SendMessageA(hwnd, LVM_SETCOLUMNORDERARRAY, 3, (LPARAM)arr); expect(TRUE, r);
SetRect(&rect, LVIR_BOUNDS, 0, -1, -1); r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect); expect(TRUE, r); expect(0, rect.left); expect(600, rect.right);
SetRect(&rect, LVIR_BOUNDS, 1, -1, -1); r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect); expect(TRUE, r); expect(0, rect.left); expect(200, rect.right);
SetRect(&rect2, LVIR_BOUNDS, 1, -1, -1); r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, 1, (LPARAM)&rect2); expect(TRUE, r); expect(0, rect2.left); expect(200, rect2.right); /* items are of the same height */ ok(rect2.top > 0, "expected positive item height\n"); expect(rect.bottom, rect2.top); expect(rect.bottom * 2 - rect.top, rect2.bottom);
SetRect(&rect, LVIR_BOUNDS, 2, -1, -1); r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect); expect(TRUE, r); expect(300, rect.left); expect(600, rect.right);
DestroyWindow(hwnd);
/* try it for non LVS_REPORT style */ hwnd = CreateWindowA(WC_LISTVIEWA, "Test", LVS_ICON, 0, 0, 100, 100, NULL, NULL, GetModuleHandleA(NULL), 0); SetRect(&rect, LVIR_BOUNDS, 1, -10, -10); r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect); expect(0, r); /* rect is unchanged */ expect(0, rect.left); expect(-10, rect.right); expect(1, rect.top); expect(-10, rect.bottom); DestroyWindow(hwnd);}
/* comparison callback for test_sorting */static INT WINAPI test_CallBackCompare(LPARAM first, LPARAM second, LPARAM lParam){ if (first == second) return 0; return (first > second ? 1 : -1);}
static void test_sorting(void){ HWND hwnd; LVITEMA item = {0}; INT r; LONG_PTR style; static CHAR names[][5] = {"A", "B", "C", "D", "0"}; CHAR buff[10];
hwnd = create_listview_control(LVS_REPORT); ok(hwnd != NULL, "failed to create a listview window\n");
/* insert some items */ item.mask = LVIF_PARAM | LVIF_STATE; item.state = LVIS_SELECTED; item.iItem = 0; item.iSubItem = 0; item.lParam = 3; r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); expect(0, r);
item.mask = LVIF_PARAM; item.iItem = 1; item.iSubItem = 0; item.lParam = 2; r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); expect(1, r);
item.mask = LVIF_STATE | LVIF_PARAM; item.state = LVIS_SELECTED; item.iItem = 2; item.iSubItem = 0; item.lParam = 4; r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); expect(2, r);
r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); expect(-1, r);
r = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0); expect(2, r);
r = SendMessageA(hwnd, LVM_SORTITEMS, 0, (LPARAM)test_CallBackCompare); expect(TRUE, r);
r = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0); expect(2, r); r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); expect(-1, r); r = SendMessageA(hwnd, LVM_GETITEMSTATE, 0, LVIS_SELECTED); expect(0, r); r = SendMessageA(hwnd, LVM_GETITEMSTATE, 1, LVIS_SELECTED); expect(LVIS_SELECTED, r); r = SendMessageA(hwnd, LVM_GETITEMSTATE, 2, LVIS_SELECTED); expect(LVIS_SELECTED, r);
DestroyWindow(hwnd);
/* switch to LVS_SORTASCENDING when some items added */ hwnd = create_listview_control(LVS_REPORT); ok(hwnd != NULL, "failed to create a listview window\n");
item.mask = LVIF_TEXT; item.iItem = 0; item.iSubItem = 0; item.pszText = names[1]; r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); expect(0, r);
item.mask = LVIF_TEXT; item.iItem = 1; item.iSubItem = 0; item.pszText = names[2]; r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); expect(1, r);
item.mask = LVIF_TEXT; item.iItem = 2; item.iSubItem = 0; item.pszText = names[0]; r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); expect(2, r);
style = GetWindowLongPtrA(hwnd, GWL_STYLE); SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SORTASCENDING); style = GetWindowLongPtrA(hwnd, GWL_STYLE); ok(style & LVS_SORTASCENDING, "Expected LVS_SORTASCENDING to be set\n");
/* no sorting performed when switched to LVS_SORTASCENDING */ item.mask = LVIF_TEXT; item.iItem = 0; item.pszText = buff; item.cchTextMax = sizeof(buff); r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); expect(TRUE, r); ok(lstrcmpA(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff);
item.iItem = 1; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); expect(TRUE, r); ok(lstrcmpA(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff);
item.iItem = 2; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); expect(TRUE, r); ok(lstrcmpA(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff);
/* adding new item doesn't resort list */ item.mask = LVIF_TEXT; item.iItem = 3; item.iSubItem = 0; item.pszText = names[3]; r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); expect(3, r);
item.mask = LVIF_TEXT; item.iItem = 0; item.pszText = buff; item.cchTextMax = sizeof(buff); r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); expect(TRUE, r); ok(lstrcmpA(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff);
item.iItem = 1; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); expect(TRUE, r); ok(lstrcmpA(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff);
item.iItem = 2; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); expect(TRUE, r); ok(lstrcmpA(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff);
item.iItem = 3; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); expect(TRUE, r); ok(lstrcmpA(buff, names[3]) == 0, "Expected '%s', got '%s'\n", names[3], buff);
/* corner case - item should be placed at first position */ item.mask = LVIF_TEXT; item.iItem = 4; item.iSubItem = 0; item.pszText = names[4]; r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); expect(0, r);
item.iItem = 0; item.pszText = buff; item.cchTextMax = sizeof(buff); r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); expect(TRUE, r); ok(lstrcmpA(buff, names[4]) == 0, "Expected '%s', got '%s'\n", names[4], buff);
item.iItem = 1; item.pszText = buff; item.cchTextMax = sizeof(buff); r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); expect(TRUE, r); ok(lstrcmpA(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff);
item.iItem = 2; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); expect(TRUE, r); ok(lstrcmpA(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff);
item.iItem = 3; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); expect(TRUE, r); ok(lstrcmpA(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff);
item.iItem = 4; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); expect(TRUE, r); ok(lstrcmpA(buff, names[3]) == 0, "Expected '%s', got '%s'\n", names[3], buff);
DestroyWindow(hwnd);}
static void test_ownerdata(void){ static char test_str[] = "test";
HWND hwnd; LONG_PTR style, ret; DWORD res; LVITEMA item;
/* it isn't possible to set LVS_OWNERDATA after creation */ if (g_is_below_5) { win_skip("set LVS_OWNERDATA after creation leads to crash on < 5.80\n"); } else { hwnd = create_listview_control(LVS_REPORT); ok(hwnd != NULL, "failed to create a listview window\n"); style = GetWindowLongPtrA(hwnd, GWL_STYLE); ok(!(style & LVS_OWNERDATA) && style, "LVS_OWNERDATA isn't expected\n");
flush_sequences(sequences, NUM_MSG_SEQUENCES);
ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_OWNERDATA); ok(ret == style, "Expected set GWL_STYLE to succeed\n"); ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq, "try to switch to LVS_OWNERDATA seq", FALSE);
style = GetWindowLongPtrA(hwnd, GWL_STYLE); ok(!(style & LVS_OWNERDATA), "LVS_OWNERDATA isn't expected\n"); DestroyWindow(hwnd); }
/* try to set LVS_OWNERDATA after creation just having it */ hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT); ok(hwnd != NULL, "failed to create a listview window\n"); style = GetWindowLongPtrA(hwnd, GWL_STYLE); ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n");
flush_sequences(sequences, NUM_MSG_SEQUENCES);
ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_OWNERDATA); ok(ret == style, "Expected set GWL_STYLE to succeed\n"); ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq, "try to switch to LVS_OWNERDATA seq", FALSE); DestroyWindow(hwnd);
/* try to remove LVS_OWNERDATA after creation just having it */ if (g_is_below_5) { win_skip("remove LVS_OWNERDATA after creation leads to crash on < 5.80\n"); } else { hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT); ok(hwnd != NULL, "failed to create a listview window\n"); style = GetWindowLongPtrA(hwnd, GWL_STYLE); ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n");
flush_sequences(sequences, NUM_MSG_SEQUENCES);
ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style & ~LVS_OWNERDATA); ok(ret == style, "Expected set GWL_STYLE to succeed\n"); ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq, "try to switch to LVS_OWNERDATA seq", FALSE); style = GetWindowLongPtrA(hwnd, GWL_STYLE); ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n"); DestroyWindow(hwnd); }
/* try select an item */ hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT); ok(hwnd != NULL, "failed to create a listview window\n"); res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0); expect(1, res); res = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0); expect(0, res); memset(&item, 0, sizeof(item)); item.stateMask = LVIS_SELECTED; item.state = LVIS_SELECTED; res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item); expect(TRUE, res); res = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0); expect(1, res); res = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0); expect(1, res); DestroyWindow(hwnd);
/* LVM_SETITEM and LVM_SETITEMTEXT is unsupported on LVS_OWNERDATA */ hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT); ok(hwnd != NULL, "failed to create a listview window\n"); res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0); expect(1, res); res = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0); expect(1, res); memset(&item, 0, sizeof(item)); item.mask = LVIF_STATE; item.iItem = 0; item.stateMask = LVIS_SELECTED; item.state = LVIS_SELECTED; res = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item); expect(FALSE, res); memset(&item, 0, sizeof(item)); item.pszText = test_str; res = SendMessageA(hwnd, LVM_SETITEMTEXTA, 0, (LPARAM)&item); expect(FALSE, res); DestroyWindow(hwnd);
/* check notifications after focused/selected changed */ hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT); ok(hwnd != NULL, "failed to create a listview window\n"); res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 20, 0); expect(1, res);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
memset(&item, 0, sizeof(item)); item.stateMask = LVIS_SELECTED; item.state = LVIS_SELECTED; res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item); expect(TRUE, res);
ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_select_focus_parent_seq, "ownerdata select notification", TRUE);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
memset(&item, 0, sizeof(item)); item.stateMask = LVIS_FOCUSED; item.state = LVIS_FOCUSED; res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item); expect(TRUE, res);
ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_select_focus_parent_seq, "ownerdata focus notification", TRUE);
/* select all, check notifications */ item.stateMask = LVIS_SELECTED; item.state = 0; res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); expect(TRUE, res);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
item.stateMask = LVIS_SELECTED; item.state = LVIS_SELECTED;
memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview)); res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); expect(TRUE, res); ok(g_nmlistview.iItem == -1, "got item %d\n", g_nmlistview.iItem); ok(g_nmlistview.iSubItem == 0, "got subitem %d\n", g_nmlistview.iSubItem); ok(g_nmlistview.uNewState == LVIS_SELECTED, "got new state 0x%08x\n", g_nmlistview.uNewState); ok(g_nmlistview.uOldState == 0, "got old state 0x%08x\n", g_nmlistview.uOldState); ok(g_nmlistview.uChanged == LVIF_STATE, "got changed 0x%08x\n", g_nmlistview.uChanged); ok(g_nmlistview.ptAction.x == 0 && g_nmlistview.ptAction.y == 0, "got wrong ptAction value\n"); ok(g_nmlistview.lParam == 0, "got wrong lparam\n");
ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_setstate_all_parent_seq, "ownerdata select all notification", FALSE);
/* select all again, note that all items are selected already */ flush_sequences(sequences, NUM_MSG_SEQUENCES); item.stateMask = LVIS_SELECTED; item.state = LVIS_SELECTED;
memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview)); res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); expect(TRUE, res); ok(g_nmlistview.iItem == -1, "got item %d\n", g_nmlistview.iItem); ok(g_nmlistview.iSubItem == 0, "got subitem %d\n", g_nmlistview.iSubItem); ok(g_nmlistview.uNewState == LVIS_SELECTED, "got new state 0x%08x\n", g_nmlistview.uNewState); ok(g_nmlistview.uOldState == 0, "got old state 0x%08x\n", g_nmlistview.uOldState); ok(g_nmlistview.uChanged == LVIF_STATE, "got changed 0x%08x\n", g_nmlistview.uChanged); ok(g_nmlistview.ptAction.x == 0 && g_nmlistview.ptAction.y == 0, "got wrong ptAction value\n"); ok(g_nmlistview.lParam == 0, "got wrong lparam\n");
ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_setstate_all_parent_seq, "ownerdata select all notification", FALSE);
/* deselect all */ flush_sequences(sequences, NUM_MSG_SEQUENCES); item.stateMask = LVIS_SELECTED; item.state = 0;
memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview)); res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); expect(TRUE, res); ok(g_nmlistview.iItem == -1, "got item %d\n", g_nmlistview.iItem); ok(g_nmlistview.iSubItem == 0, "got subitem %d\n", g_nmlistview.iSubItem); ok(g_nmlistview.uNewState == 0, "got new state 0x%08x\n", g_nmlistview.uNewState); ok(g_nmlistview.uOldState == LVIS_SELECTED, "got old state 0x%08x\n", g_nmlistview.uOldState); ok(g_nmlistview.uChanged == LVIF_STATE, "got changed 0x%08x\n", g_nmlistview.uChanged); ok(g_nmlistview.ptAction.x == 0 && g_nmlistview.ptAction.y == 0, "got wrong ptAction value\n"); ok(g_nmlistview.lParam == 0, "got wrong lparam\n");
ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_deselect_all_parent_seq, "ownerdata deselect all notification", TRUE);
/* nothing selected, deselect all again */ flush_sequences(sequences, NUM_MSG_SEQUENCES); item.stateMask = LVIS_SELECTED; item.state = 0;
res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); expect(TRUE, res);
ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "ownerdata deselect all notification", FALSE);
/* select one, then deselect all */ item.stateMask = LVIS_SELECTED; item.state = LVIS_SELECTED; res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item); expect(TRUE, res); flush_sequences(sequences, NUM_MSG_SEQUENCES); item.stateMask = LVIS_SELECTED; item.state = 0;
memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview)); res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); expect(TRUE, res); ok(g_nmlistview.iItem == -1, "got item %d\n", g_nmlistview.iItem); ok(g_nmlistview.iSubItem == 0, "got subitem %d\n", g_nmlistview.iSubItem); ok(g_nmlistview.uNewState == 0, "got new state 0x%08x\n", g_nmlistview.uNewState); ok(g_nmlistview.uOldState == LVIS_SELECTED, "got old state 0x%08x\n", g_nmlistview.uOldState); ok(g_nmlistview.uChanged == LVIF_STATE, "got changed 0x%08x\n", g_nmlistview.uChanged); ok(g_nmlistview.ptAction.x == 0 && g_nmlistview.ptAction.y == 0, "got wrong ptAction value\n"); ok(g_nmlistview.lParam == 0, "got wrong lparam\n");
ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_deselect_all_parent_seq, "ownerdata select all notification", TRUE);
/* remove focused, try to focus all */ item.stateMask = LVIS_FOCUSED; item.state = LVIS_FOCUSED; res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item); expect(TRUE, res); item.stateMask = LVIS_FOCUSED; item.state = 0; res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); expect(TRUE, res); item.stateMask = LVIS_FOCUSED; res = SendMessageA(hwnd, LVM_GETITEMSTATE, 0, LVIS_FOCUSED); expect(0, res);
/* setting all to focused returns failure value */ flush_sequences(sequences, NUM_MSG_SEQUENCES); item.stateMask = LVIS_FOCUSED; item.state = LVIS_FOCUSED;
res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); expect(FALSE, res);
ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "ownerdata focus all notification", FALSE);
/* focus single item, remove all */ item.stateMask = LVIS_FOCUSED; item.state = LVIS_FOCUSED; res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item); expect(TRUE, res); flush_sequences(sequences, NUM_MSG_SEQUENCES); item.stateMask = LVIS_FOCUSED; item.state = 0;
memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview)); res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); expect(TRUE, res); ok(g_nmlistview.iItem == -1, "got item %d\n", g_nmlistview.iItem); ok(g_nmlistview.iSubItem == 0, "got subitem %d\n", g_nmlistview.iSubItem); ok(g_nmlistview.uNewState == 0, "got new state 0x%08x\n", g_nmlistview.uNewState); ok(g_nmlistview.uOldState == LVIS_FOCUSED, "got old state 0x%08x\n", g_nmlistview.uOldState); ok(g_nmlistview.uChanged == LVIF_STATE, "got changed 0x%08x\n", g_nmlistview.uChanged); ok(g_nmlistview.ptAction.x == 0 && g_nmlistview.ptAction.y == 0, "got wrong ptAction value\n"); ok(g_nmlistview.lParam == 0, "got wrong lparam\n");
ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_defocus_all_parent_seq, "ownerdata remove focus all notification", TRUE);
/* set all cut */ flush_sequences(sequences, NUM_MSG_SEQUENCES); item.stateMask = LVIS_CUT; item.state = LVIS_CUT;
memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview)); res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); expect(TRUE, res); ok(g_nmlistview.iItem == -1, "got item %d\n", g_nmlistview.iItem); ok(g_nmlistview.iSubItem == 0, "got subitem %d\n", g_nmlistview.iSubItem); ok(g_nmlistview.uNewState == LVIS_CUT, "got new state 0x%08x\n", g_nmlistview.uNewState); ok(g_nmlistview.uOldState == 0, "got old state 0x%08x\n", g_nmlistview.uOldState); ok(g_nmlistview.uChanged == LVIF_STATE, "got changed 0x%08x\n", g_nmlistview.uChanged); ok(g_nmlistview.ptAction.x == 0 && g_nmlistview.ptAction.y == 0, "got wrong ptAction value\n"); ok(g_nmlistview.lParam == 0, "got wrong lparam\n");
ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_setstate_all_parent_seq, "ownerdata cut all notification", FALSE);
/* all marked cut, try again */ flush_sequences(sequences, NUM_MSG_SEQUENCES); item.stateMask = LVIS_CUT; item.state = LVIS_CUT;
memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview)); res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); expect(TRUE, res); ok(g_nmlistview.iItem == -1, "got item %d\n", g_nmlistview.iItem); ok(g_nmlistview.iSubItem == 0, "got subitem %d\n", g_nmlistview.iSubItem); ok(g_nmlistview.uNewState == LVIS_CUT, "got new state 0x%08x\n", g_nmlistview.uNewState); ok(g_nmlistview.uOldState == 0, "got old state 0x%08x\n", g_nmlistview.uOldState); ok(g_nmlistview.uChanged == LVIF_STATE, "got changed 0x%08x\n", g_nmlistview.uChanged); ok(g_nmlistview.ptAction.x == 0 && g_nmlistview.ptAction.y == 0, "got wrong ptAction value\n"); ok(g_nmlistview.lParam == 0, "got wrong lparam\n");
ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_setstate_all_parent_seq, "ownerdata cut all notification #2", FALSE);
DestroyWindow(hwnd);
/* check notifications on LVM_GETITEM */ /* zero callback mask */ hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT); ok(hwnd != NULL, "failed to create a listview window\n"); res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0); expect(1, res);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
memset(&item, 0, sizeof(item)); item.stateMask = LVIS_SELECTED; item.mask = LVIF_STATE; res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item); expect(TRUE, res);
ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "ownerdata getitem selected state 1", FALSE);
/* non zero callback mask but not we asking for */ res = SendMessageA(hwnd, LVM_SETCALLBACKMASK, LVIS_OVERLAYMASK, 0); expect(TRUE, res);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
memset(&item, 0, sizeof(item)); item.stateMask = LVIS_SELECTED; item.mask = LVIF_STATE; res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item); expect(TRUE, res);
ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "ownerdata getitem selected state 2", FALSE);
/* LVIS_OVERLAYMASK callback mask, asking for index */ flush_sequences(sequences, NUM_MSG_SEQUENCES);
memset(&item, 0, sizeof(item)); item.stateMask = LVIS_OVERLAYMASK; item.mask = LVIF_STATE; res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item); expect(TRUE, res);
ok_sequence(sequences, PARENT_SEQ_INDEX, single_getdispinfo_parent_seq, "ownerdata getitem selected state 2", FALSE);
DestroyWindow(hwnd);
/* LVS_SORTASCENDING/LVS_SORTDESCENDING aren't compatible with LVS_OWNERDATA */ hwnd = create_listview_control(LVS_OWNERDATA | LVS_SORTASCENDING | LVS_REPORT); ok(hwnd != NULL, "failed to create a listview window\n"); style = GetWindowLongPtrA(hwnd, GWL_STYLE); ok(style & LVS_OWNERDATA, "Expected LVS_OWNERDATA\n"); ok(style & LVS_SORTASCENDING, "Expected LVS_SORTASCENDING to be set\n"); SetWindowLongPtrA(hwnd, GWL_STYLE, style & ~LVS_SORTASCENDING); style = GetWindowLongPtrA(hwnd, GWL_STYLE); ok(!(style & LVS_SORTASCENDING), "Expected LVS_SORTASCENDING not set\n"); DestroyWindow(hwnd); /* apparently it's allowed to switch these style on after creation */ hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT); ok(hwnd != NULL, "failed to create a listview window\n"); style = GetWindowLongPtrA(hwnd, GWL_STYLE); ok(style & LVS_OWNERDATA, "Expected LVS_OWNERDATA\n"); SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SORTASCENDING); style = GetWindowLongPtrA(hwnd, GWL_STYLE); ok(style & LVS_SORTASCENDING, "Expected LVS_SORTASCENDING to be set\n"); DestroyWindow(hwnd);
hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT); ok(hwnd != NULL, "failed to create a listview window\n"); style = GetWindowLongPtrA(hwnd, GWL_STYLE); ok(style & LVS_OWNERDATA, "Expected LVS_OWNERDATA\n"); SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SORTDESCENDING); style = GetWindowLongPtrA(hwnd, GWL_STYLE); ok(style & LVS_SORTDESCENDING, "Expected LVS_SORTDESCENDING to be set\n"); DestroyWindow(hwnd);
/* The focused item is updated after the invalidation */ hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT); ok(hwnd != NULL, "failed to create a listview window\n"); res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 3, 0); expect(TRUE, res);
memset(&item, 0, sizeof(item)); item.stateMask = LVIS_FOCUSED; item.state = LVIS_FOCUSED; res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item); expect(TRUE, res);
flush_sequences(sequences, NUM_MSG_SEQUENCES); res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 0, 0); expect(TRUE, res); ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "ownerdata setitemcount", FALSE);
res = SendMessageA(hwnd, LVM_GETNEXTITEM, -1, LVNI_FOCUSED); expect(-1, res); DestroyWindow(hwnd);}
static void test_norecompute(void){ static CHAR testA[] = "test"; CHAR buff[10]; LVITEMA item; HWND hwnd; DWORD res;
/* self containing control */ hwnd = create_listview_control(LVS_REPORT); ok(hwnd != NULL, "failed to create a listview window\n"); memset(&item, 0, sizeof(item)); item.mask = LVIF_TEXT | LVIF_STATE; item.iItem = 0; item.stateMask = LVIS_SELECTED; item.state = LVIS_SELECTED; item.pszText = testA; res = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item); expect(0, res); /* retrieve with LVIF_NORECOMPUTE */ item.mask = LVIF_TEXT | LVIF_NORECOMPUTE; item.iItem = 0; item.pszText = buff; item.cchTextMax = ARRAY_SIZE(buff); res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item); expect(TRUE, res); ok(lstrcmpA(buff, testA) == 0, "Expected (%s), got (%s)\n", testA, buff);
item.mask = LVIF_TEXT; item.iItem = 1; item.pszText = LPSTR_TEXTCALLBACKA; res = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item); expect(1, res);
item.mask = LVIF_TEXT | LVIF_NORECOMPUTE; item.iItem = 1; item.pszText = buff; item.cchTextMax = ARRAY_SIZE(buff);
flush_sequences(sequences, NUM_MSG_SEQUENCES); res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item); expect(TRUE, res); ok(item.pszText == LPSTR_TEXTCALLBACKA, "Expected (%p), got (%p)\n", LPSTR_TEXTCALLBACKA, (VOID*)item.pszText); ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "retrieve with LVIF_NORECOMPUTE seq", FALSE);
DestroyWindow(hwnd);
/* LVS_OWNERDATA */ hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT); ok(hwnd != NULL, "failed to create a listview window\n");
item.mask = LVIF_STATE; item.stateMask = LVIS_SELECTED; item.state = LVIS_SELECTED; item.iItem = 0; res = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item); expect(0, res);
item.mask = LVIF_TEXT | LVIF_NORECOMPUTE; item.iItem = 0; item.pszText = buff; item.cchTextMax = ARRAY_SIZE(buff); flush_sequences(sequences, NUM_MSG_SEQUENCES); res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item); expect(TRUE, res); ok(item.pszText == LPSTR_TEXTCALLBACKA, "Expected (%p), got (%p)\n", LPSTR_TEXTCALLBACKA, (VOID*)item.pszText); ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "retrieve with LVIF_NORECOMPUTE seq 2", FALSE);
DestroyWindow(hwnd);}
static void test_nosortheader(void){ HWND hwnd, header; LONG_PTR style;
hwnd = create_listview_control(LVS_REPORT); ok(hwnd != NULL, "failed to create a listview window\n");
header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); ok(IsWindow(header), "header expected\n");
style = GetWindowLongPtrA(header, GWL_STYLE); ok(style & HDS_BUTTONS, "expected header to have HDS_BUTTONS\n");
style = GetWindowLongPtrA(hwnd, GWL_STYLE); SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_NOSORTHEADER); /* HDS_BUTTONS retained */ style = GetWindowLongPtrA(header, GWL_STYLE); ok(style & HDS_BUTTONS, "expected header to retain HDS_BUTTONS\n");
DestroyWindow(hwnd);
/* create with LVS_NOSORTHEADER */ hwnd = create_listview_control(LVS_NOSORTHEADER | LVS_REPORT); ok(hwnd != NULL, "failed to create a listview window\n");
header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); ok(IsWindow(header), "header expected\n");
style = GetWindowLongPtrA(header, GWL_STYLE); ok(!(style & HDS_BUTTONS), "expected header to have no HDS_BUTTONS\n");
style = GetWindowLongPtrA(hwnd, GWL_STYLE); SetWindowLongPtrA(hwnd, GWL_STYLE, style & ~LVS_NOSORTHEADER); /* not changed here */ style = GetWindowLongPtrA(header, GWL_STYLE); ok(!(style & HDS_BUTTONS), "expected header to have no HDS_BUTTONS\n");
DestroyWindow(hwnd);}
static void test_setredraw(void){ HWND hwnd; DWORD_PTR style; DWORD ret; HDC hdc; RECT rect;
hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT); ok(hwnd != NULL, "failed to create a listview window\n");
/* Passing WM_SETREDRAW to DefWinProc removes WS_VISIBLE. ListView seems to handle it internally without DefWinProc */
/* default value first */ ret = SendMessageA(hwnd, WM_SETREDRAW, TRUE, 0); expect(0, ret); /* disable */ style = GetWindowLongPtrA(hwnd, GWL_STYLE); ok(style & WS_VISIBLE, "Expected WS_VISIBLE to be set\n"); ret = SendMessageA(hwnd, WM_SETREDRAW, FALSE, 0); expect(0, ret); style = GetWindowLongPtrA(hwnd, GWL_STYLE); ok(style & WS_VISIBLE, "Expected WS_VISIBLE to be set\n"); ret = SendMessageA(hwnd, WM_SETREDRAW, TRUE, 0); expect(0, ret);
/* check update rect after redrawing */ ret = SendMessageA(hwnd, WM_SETREDRAW, FALSE, 0); expect(0, ret); InvalidateRect(hwnd, NULL, FALSE); RedrawWindow(hwnd, NULL, NULL, RDW_UPDATENOW); rect.right = rect.bottom = 1; GetUpdateRect(hwnd, &rect, FALSE); expect(0, rect.right); expect(0, rect.bottom);
/* WM_ERASEBKGND */ hdc = GetWindowDC(hwndparent); ret = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0); expect(TRUE, ret); ret = SendMessageA(hwnd, WM_SETREDRAW, FALSE, 0); expect(0, ret); ret = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0); expect(TRUE, ret); ret = SendMessageA(hwnd, WM_SETREDRAW, TRUE, 0); expect(0, ret); ReleaseDC(hwndparent, hdc);
/* check notification messages to show that repainting is disabled */ ret = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0); expect(TRUE, ret); ret = SendMessageA(hwnd, WM_SETREDRAW, FALSE, 0); expect(0, ret); flush_sequences(sequences, NUM_MSG_SEQUENCES);
InvalidateRect(hwnd, NULL, TRUE); UpdateWindow(hwnd); ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "redraw after WM_SETREDRAW (FALSE)", FALSE);
ret = SendMessageA(hwnd, LVM_SETBKCOLOR, 0, CLR_NONE); expect(TRUE, ret); flush_sequences(sequences, NUM_MSG_SEQUENCES); InvalidateRect(hwnd, NULL, TRUE); UpdateWindow(hwnd); ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "redraw after WM_SETREDRAW (FALSE) with CLR_NONE bkgnd", FALSE);
/* message isn't forwarded to header */ subclass_header(hwnd); flush_sequences(sequences, NUM_MSG_SEQUENCES); ret = SendMessageA(hwnd, WM_SETREDRAW, FALSE, 0); expect(0, ret); ok_sequence(sequences, LISTVIEW_SEQ_INDEX, setredraw_seq, "WM_SETREDRAW: not forwarded to header", FALSE);
DestroyWindow(hwnd);}
static void test_hittest(void){ HWND hwnd; DWORD r; RECT bounds; LVITEMA item; static CHAR text[] = "1234567890ABCDEFGHIJKLMNOPQRST"; POINT pos; INT x, y, i; WORD vert; HIMAGELIST himl, himl2; HBITMAP hbmp;
hwnd = create_listview_control(LVS_REPORT); ok(hwnd != NULL, "failed to create a listview window\n");
/* LVS_REPORT with a single subitem (2 columns) */ insert_column(hwnd, 0); insert_column(hwnd, 1); insert_item(hwnd, 0);
item.iSubItem = 0; /* the only purpose of that line is to be as long as a half item rect */ item.pszText = text; r = SendMessageA(hwnd, LVM_SETITEMTEXTA, 0, (LPARAM)&item); expect(TRUE, r);
r = SendMessageA(hwnd, LVM_SETCOLUMNWIDTH, 0, MAKELPARAM(100, 0)); expect(TRUE, r); r = SendMessageA(hwnd, LVM_SETCOLUMNWIDTH, 1, MAKELPARAM(100, 0)); expect(TRUE, r);
SetRect(&bounds, LVIR_BOUNDS, 0, 0, 0); r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&bounds); expect(1, r); ok(bounds.bottom - bounds.top > 0, "Expected non zero item height\n"); ok(bounds.right - bounds.left > 0, "Expected non zero item width\n"); r = SendMessageA(hwnd, LVM_GETITEMSPACING, TRUE, 0); vert = HIWORD(r); ok(bounds.bottom - bounds.top == vert, "Vertical spacing inconsistent (%d != %d)\n", bounds.bottom - bounds.top, vert); r = SendMessageA(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pos); expect(TRUE, r);
/* LVS_EX_FULLROWSELECT not set, no icons attached */
/* outside columns by x position - valid is [0, 199] */ x = -1; y = pos.y + (bounds.bottom - bounds.top) / 2; test_lvm_hittest(hwnd, x, y, -1, LVHT_TOLEFT, 0, FALSE, FALSE); test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE);
x = pos.x + 50; /* column half width */ y = pos.y + (bounds.bottom - bounds.top) / 2; test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMLABEL, 0, FALSE, FALSE); test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE); x = pos.x + 150; /* outside column */ y = pos.y + (bounds.bottom - bounds.top) / 2; test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, FALSE); test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE); y = (bounds.bottom - bounds.top) / 2; test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, TRUE); test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE); /* outside possible client rectangle (to right) */ x = pos.x + 500; y = pos.y + (bounds.bottom - bounds.top) / 2; test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, FALSE); test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE); y = (bounds.bottom - bounds.top) / 2; test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, TRUE); test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE); /* subitem returned with -1 item too */ x = pos.x + 150; y = bounds.top - vert; test_lvm_subitemhittest(hwnd, x, y, -1, 1, LVHT_NOWHERE, FALSE, FALSE, FALSE); test_lvm_subitemhittest(hwnd, x, y - vert + 1, -1, 1, LVHT_NOWHERE, FALSE, FALSE, FALSE); /* return values appear to underflow with negative indices */ i = -2; y = y - vert; while (i > -10) { test_lvm_subitemhittest(hwnd, x, y, i, 1, LVHT_ONITEMLABEL, TRUE, FALSE, TRUE); test_lvm_subitemhittest(hwnd, x, y - vert + 1, i, 1, LVHT_ONITEMLABEL, TRUE, FALSE, TRUE); y = y - vert; i--; } /* parent client area is 100x100 by default */ MoveWindow(hwnd, 0, 0, 300, 100, FALSE); x = pos.x + 150; /* outside column */ y = pos.y + (bounds.bottom - bounds.top) / 2; test_lvm_hittest(hwnd, x, y, -1, LVHT_NOWHERE, 0, FALSE, FALSE); test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE); y = (bounds.bottom - bounds.top) / 2; test_lvm_hittest(hwnd, x, y, -1, LVHT_NOWHERE, 0, FALSE, TRUE); test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE); /* the same with LVS_EX_FULLROWSELECT */ SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT); x = pos.x + 150; /* outside column */ y = pos.y + (bounds.bottom - bounds.top) / 2; test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEM, LVHT_ONITEMLABEL, FALSE, FALSE); test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE); y = (bounds.bottom - bounds.top) / 2; test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE); MoveWindow(hwnd, 0, 0, 100, 100, FALSE); x = pos.x + 150; /* outside column */ y = pos.y + (bounds.bottom - bounds.top) / 2; test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, FALSE); test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE); y = (bounds.bottom - bounds.top) / 2; test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, TRUE); test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE); /* outside possible client rectangle (to right) */ x = pos.x + 500; y = pos.y + (bounds.bottom - bounds.top) / 2; test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, FALSE); test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE); y = (bounds.bottom - bounds.top) / 2; test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, TRUE); test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE); /* try with icons, state icons index is 1 based so at least 2 bitmaps needed */ himl = pImageList_Create(16, 16, 0, 4, 4); ok(himl != NULL, "failed to create imagelist\n"); hbmp = CreateBitmap(16, 16, 1, 1, NULL); ok(hbmp != NULL, "failed to create bitmap\n"); r = pImageList_Add(himl, hbmp, 0); ok(r == 0, "should be zero\n"); hbmp = CreateBitmap(16, 16, 1, 1, NULL); ok(hbmp != NULL, "failed to create bitmap\n"); r = pImageList_Add(himl, hbmp, 0); ok(r == 1, "should be one\n");
r = SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)himl); expect(0, r);
item.mask = LVIF_IMAGE; item.iImage = 0; item.iItem = 0; item.iSubItem = 0; r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item); expect(TRUE, r); /* on state icon */ x = pos.x + 8; y = pos.y + (bounds.bottom - bounds.top) / 2; test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMSTATEICON, 0, FALSE, FALSE); test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE); y = (bounds.bottom - bounds.top) / 2; test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE);
/* state icons indices are 1 based, check with valid index */ item.mask = LVIF_STATE; item.state = INDEXTOSTATEIMAGEMASK(1); item.stateMask = LVIS_STATEIMAGEMASK; item.iItem = 0; item.iSubItem = 0; r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item); expect(TRUE, r); /* on state icon */ x = pos.x + 8; y = pos.y + (bounds.bottom - bounds.top) / 2; test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMSTATEICON, 0, FALSE, FALSE); test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE); y = (bounds.bottom - bounds.top) / 2; test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE);
himl2 = (HIMAGELIST)SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, 0); ok(himl2 == himl, "should return handle\n");
r = SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)himl); expect(0, r); /* on item icon */ x = pos.x + 8; y = pos.y + (bounds.bottom - bounds.top) / 2; test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMICON, 0, FALSE, FALSE); test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMICON, FALSE, FALSE, FALSE); y = (bounds.bottom - bounds.top) / 2; test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMICON, FALSE, FALSE, FALSE);
DestroyWindow(hwnd);}
static void test_getviewrect(void){ HWND hwnd; DWORD r; RECT rect; LVITEMA item;
hwnd = create_listview_control(LVS_REPORT); ok(hwnd != NULL, "failed to create a listview window\n");
/* empty */ r = SendMessageA(hwnd, LVM_GETVIEWRECT, 0, (LPARAM)&rect); expect(TRUE, r);
insert_column(hwnd, 0); insert_column(hwnd, 1);
memset(&item, 0, sizeof(item)); item.iItem = 0; item.iSubItem = 0; r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item); ok(!r, "got %d\n", r);
r = SendMessageA(hwnd, LVM_SETCOLUMNWIDTH, 0, MAKELPARAM(100, 0)); expect(TRUE, r); r = SendMessageA(hwnd, LVM_SETCOLUMNWIDTH, 1, MAKELPARAM(120, 0)); expect(TRUE, r);
SetRect(&rect, -1, -1, -1, -1); r = SendMessageA(hwnd, LVM_GETVIEWRECT, 0, (LPARAM)&rect); expect(TRUE, r); /* left is set to (2e31-1) - XP SP2 */ expect(0, rect.right); expect(0, rect.top); expect(0, rect.bottom);
/* switch to LVS_ICON */ SetWindowLongA(hwnd, GWL_STYLE, GetWindowLongA(hwnd, GWL_STYLE) & ~LVS_REPORT);
SetRect(&rect, -1, -1, -1, -1); r = SendMessageA(hwnd, LVM_GETVIEWRECT, 0, (LPARAM)&rect); expect(TRUE, r); expect(0, rect.left); expect(0, rect.top); /* precise value differs for 2k, XP and Vista */ ok(rect.bottom > 0, "Expected positive bottom value, got %d\n", rect.bottom); ok(rect.right > 0, "Expected positive right value, got %d\n", rect.right);
DestroyWindow(hwnd);}
static void test_getitemposition(void){ HWND hwnd, header; DWORD r; POINT pt; RECT rect;
hwnd = create_listview_control(LVS_REPORT); ok(hwnd != NULL, "failed to create a listview window\n"); header = subclass_header(hwnd);
/* LVS_REPORT, single item, no columns added */ insert_item(hwnd, 0);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
pt.x = pt.y = -1; r = SendMessageA(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pt); expect(TRUE, r); ok_sequence(sequences, LISTVIEW_SEQ_INDEX, getitemposition_seq1, "get item position 1", FALSE);
/* LVS_REPORT, single item, single column */ insert_column(hwnd, 0);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
pt.x = pt.y = -1; r = SendMessageA(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pt); expect(TRUE, r); ok_sequence(sequences, LISTVIEW_SEQ_INDEX, getitemposition_seq2, "get item position 2", TRUE);
SetRectEmpty(&rect); r = SendMessageA(header, HDM_GETITEMRECT, 0, (LPARAM)&rect); ok(r, "got %d\n", r); /* some padding? */ expect(2, pt.x); /* offset by header height */ expect(rect.bottom - rect.top, pt.y);
DestroyWindow(hwnd);}
static void test_getitemrect(void){ HWND hwnd; HIMAGELIST himl, himl_ret; HBITMAP hbm; RECT rect; DWORD r; LVITEMA item; LVCOLUMNA col; INT order[2]; POINT pt;
/* rectangle isn't empty for empty text items */ hwnd = create_listview_control(LVS_LIST); memset(&item, 0, sizeof(item)); item.mask = 0; item.iItem = 0; r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item); expect(0, r); rect.left = LVIR_LABEL; r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect); expect(TRUE, r); expect(0, rect.left); expect(0, rect.top); /* estimate it as width / height ratio */todo_wine ok((rect.right / rect.bottom) >= 5, "got right %d, bottom %d\n", rect.right, rect.bottom); DestroyWindow(hwnd);
hwnd = create_listview_control(LVS_REPORT); ok(hwnd != NULL, "failed to create a listview window\n");
/* empty item */ memset(&item, 0, sizeof(item)); item.iItem = 0; item.iSubItem = 0; r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item); expect(0, r);
SetRect(&rect, LVIR_BOUNDS, -1, -1, -1); r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect); expect(TRUE, r);
/* zero width rectangle with no padding */ expect(0, rect.left); expect(0, rect.right);
insert_column(hwnd, 0); insert_column(hwnd, 1);
col.mask = LVCF_WIDTH; col.cx = 50; r = SendMessageA(hwnd, LVM_SETCOLUMNA, 0, (LPARAM)&col); expect(TRUE, r);
col.mask = LVCF_WIDTH; col.cx = 100; r = SendMessageA(hwnd, LVM_SETCOLUMNA, 1, (LPARAM)&col); expect(TRUE, r);
SetRect(&rect, LVIR_BOUNDS, -1, -1, -1); r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect); expect(TRUE, r);
/* still no left padding */ expect(0, rect.left); expect(150, rect.right);
SetRect(&rect, LVIR_SELECTBOUNDS, -1, -1, -1); r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect); expect(TRUE, r); /* padding */ expect(2, rect.left);
SetRect(&rect, LVIR_LABEL, -1, -1, -1); r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect); expect(TRUE, r); /* padding, column width */ expect(2, rect.left); expect(50, rect.right);
/* no icons attached */ SetRect(&rect, LVIR_ICON, -1, -1, -1); r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect); expect(TRUE, r); /* padding */ expect(2, rect.left); expect(2, rect.right);
/* change order */ order[0] = 1; order[1] = 0; r = SendMessageA(hwnd, LVM_SETCOLUMNORDERARRAY, 2, (LPARAM)&order); expect(TRUE, r); pt.x = -1; r = SendMessageA(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pt); expect(TRUE, r); /* 1 indexed column width + padding */ expect(102, pt.x); /* rect is at zero too */ SetRect(&rect, LVIR_BOUNDS, -1, -1, -1); r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect); expect(TRUE, r); expect(0, rect.left); /* just width sum */ expect(150, rect.right);
SetRect(&rect, LVIR_SELECTBOUNDS, -1, -1, -1); r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect); expect(TRUE, r); /* column width + padding */ expect(102, rect.left);
/* back to initial order */ order[0] = 0; order[1] = 1; r = SendMessageA(hwnd, LVM_SETCOLUMNORDERARRAY, 2, (LPARAM)&order); expect(TRUE, r);
/* state icons */ himl = pImageList_Create(16, 16, 0, 2, 2); ok(himl != NULL, "failed to create imagelist\n"); hbm = CreateBitmap(16, 16, 1, 1, NULL); ok(hbm != NULL, "failed to create bitmap\n"); r = pImageList_Add(himl, hbm, 0); expect(0, r); hbm = CreateBitmap(16, 16, 1, 1, NULL); ok(hbm != NULL, "failed to create bitmap\n"); r = pImageList_Add(himl, hbm, 0); expect(1, r);
r = SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)himl); expect(0, r);
item.mask = LVIF_STATE; item.state = INDEXTOSTATEIMAGEMASK(1); item.stateMask = LVIS_STATEIMAGEMASK; item.iItem = 0; item.iSubItem = 0; r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item); expect(TRUE, r);
/* icon bounds */ SetRect(&rect, LVIR_ICON, -1, -1, -1); r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect); expect(TRUE, r); /* padding + stateicon width */ expect(18, rect.left); expect(18, rect.right); /* label bounds */ SetRect(&rect, LVIR_LABEL, -1, -1, -1); r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect); expect(TRUE, r); /* padding + stateicon width -> column width */ expect(18, rect.left); expect(50, rect.right);
himl_ret = (HIMAGELIST)SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, 0); ok(himl_ret == himl, "got %p, expected %p\n", himl_ret, himl);
r = SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)himl); expect(0, r);
item.mask = LVIF_STATE | LVIF_IMAGE; item.iImage = 1; item.state = 0; item.stateMask = ~0; item.iItem = 0; item.iSubItem = 0; r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item); expect(TRUE, r);
/* icon bounds */ SetRect(&rect, LVIR_ICON, -1, -1, -1); r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect); expect(TRUE, r); /* padding, icon width */ expect(2, rect.left); expect(18, rect.right); /* label bounds */ SetRect(&rect, LVIR_LABEL, -1, -1, -1); r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect); expect(TRUE, r); /* padding + icon width -> column width */ expect(18, rect.left); expect(50, rect.right);
/* select bounds */ SetRect(&rect, LVIR_SELECTBOUNDS, -1, -1, -1); r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect); expect(TRUE, r); /* padding, column width */ expect(2, rect.left); expect(50, rect.right);
/* try with indentation */ item.mask = LVIF_INDENT; item.iIndent = 1; item.iItem = 0; item.iSubItem = 0; r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item); expect(TRUE, r);
/* bounds */ SetRect(&rect, LVIR_BOUNDS, -1, -1, -1); r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect); expect(TRUE, r); /* padding + 1 icon width, column width */ expect(0, rect.left); expect(150, rect.right);
/* select bounds */ SetRect(&rect, LVIR_SELECTBOUNDS, -1, -1, -1); r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect); expect(TRUE, r); /* padding + 1 icon width, column width */ expect(2 + 16, rect.left); expect(50, rect.right);
/* label bounds */ SetRect(&rect, LVIR_LABEL, -1, -1, -1); r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect); expect(TRUE, r); /* padding + 2 icon widths, column width */ expect(2 + 16*2, rect.left); expect(50, rect.right);
/* icon bounds */ SetRect(&rect, LVIR_ICON, -1, -1, -1); r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect); expect(TRUE, r); /* padding + 1 icon width indentation, icon width */ expect(2 + 16, rect.left); expect(34, rect.right);
DestroyWindow(hwnd);}
static void test_editbox(void){ static CHAR testitemA[] = "testitem"; static CHAR testitem1A[] = "testitem_quitelongname"; static CHAR testitem2A[] = "testITEM_quitelongname"; static CHAR buffer[25]; HWND hwnd, hwndedit, hwndedit2, header; LVITEMA item; INT r;
hwnd = create_listview_control(LVS_EDITLABELS | LVS_REPORT); ok(hwnd != NULL, "failed to create a listview window\n");
insert_column(hwnd, 0);
memset(&item, 0, sizeof(item)); item.mask = LVIF_TEXT; item.pszText = testitemA; item.iItem = 0; item.iSubItem = 0; r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item); expect(0, r);
/* test notifications without edit created */ flush_sequences(sequences, NUM_MSG_SEQUENCES); r = SendMessageA(hwnd, WM_COMMAND, MAKEWPARAM(0, EN_SETFOCUS), (LPARAM)0xdeadbeef); expect(0, r); ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "edit box WM_COMMAND (EN_SETFOCUS), no edit created", FALSE); /* same thing but with valid window */ hwndedit = CreateWindowA(WC_EDITA, "Test edit", WS_VISIBLE | WS_CHILD, 0, 0, 20, 10, hwnd, (HMENU)1, (HINSTANCE)GetWindowLongPtrA(hwnd, GWLP_HINSTANCE), 0); flush_sequences(sequences, NUM_MSG_SEQUENCES); r = SendMessageA(hwnd, WM_COMMAND, MAKEWPARAM(0, EN_SETFOCUS), (LPARAM)hwndedit); expect(0, r); ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "edit box WM_COMMAND (EN_SETFOCUS), no edit created #2", FALSE); DestroyWindow(hwndedit);
/* setting focus is necessary */ SetFocus(hwnd); hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0); ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
/* test children Z-order after Edit box created */ header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); ok(IsWindow(header), "Expected header to be created\n"); ok(GetTopWindow(hwnd) == header, "Expected header to be on top\n"); ok(GetNextWindow(header, GW_HWNDNEXT) == hwndedit, "got %p\n", GetNextWindow(header, GW_HWNDNEXT));
/* modify initial string */ r = SendMessageA(hwndedit, WM_SETTEXT, 0, (LPARAM)testitem1A); expect(TRUE, r);
/* edit window is resized and repositioned, check again for Z-order - it should be preserved */ ok(GetTopWindow(hwnd) == header, "Expected header to be on top\n"); ok(GetNextWindow(header, GW_HWNDNEXT) == hwndedit, "got %p\n", GetNextWindow(header, GW_HWNDNEXT));
/* return focus to listview */ SetFocus(hwnd);
memset(&item, 0, sizeof(item)); item.mask = LVIF_TEXT; item.pszText = buffer; item.cchTextMax = sizeof(buffer); item.iItem = 0; item.iSubItem = 0; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item); expect(TRUE, r);
ok(strcmp(buffer, testitem1A) == 0, "Expected item text to change\n");
/* send LVM_EDITLABEL on already created edit */ SetFocus(hwnd); hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0); ok(IsWindow(hwndedit), "Expected Edit window to be created\n"); /* focus will be set to edit */ ok(GetFocus() == hwndedit, "Expected Edit window to be focused\n"); hwndedit2 = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0); ok(IsWindow(hwndedit2), "Expected Edit window to be created\n");
/* creating label disabled when control isn't focused */ SetFocus(0); hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0); todo_wine ok(hwndedit == NULL, "Expected Edit window not to be created\n");
/* check EN_KILLFOCUS handling */ memset(&item, 0, sizeof(item)); item.pszText = testitemA; item.iItem = 0; item.iSubItem = 0; r = SendMessageA(hwnd, LVM_SETITEMTEXTA, 0, (LPARAM)&item); expect(TRUE, r);
SetFocus(hwnd); hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0); ok(IsWindow(hwndedit), "Expected Edit window to be created\n"); /* modify edit and notify control that it lost focus */ r = SendMessageA(hwndedit, WM_SETTEXT, 0, (LPARAM)testitem1A); expect(TRUE, r); g_editbox_disp_info.item.pszText = NULL; r = SendMessageA(hwnd, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), (LPARAM)hwndedit); expect(0, r); ok(g_editbox_disp_info.item.pszText != NULL, "expected notification with not null text\n");
memset(&item, 0, sizeof(item)); item.pszText = buffer; item.cchTextMax = sizeof(buffer); item.iItem = 0; item.iSubItem = 0; r = SendMessageA(hwnd, LVM_GETITEMTEXTA, 0, (LPARAM)&item); expect(lstrlenA(item.pszText), r); ok(strcmp(buffer, testitem1A) == 0, "Expected item text to change\n"); ok(!IsWindow(hwndedit), "Expected Edit window to be freed\n");
/* change item name to differ in casing only */ SetFocus(hwnd); hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0); ok(IsWindow(hwndedit), "Expected Edit window to be created\n"); /* modify edit and notify control that it lost focus */ r = SendMessageA(hwndedit, WM_SETTEXT, 0, (LPARAM)testitem2A); expect(TRUE, r); g_editbox_disp_info.item.pszText = NULL; r = SendMessageA(hwnd, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), (LPARAM)hwndedit); expect(0, r); ok(g_editbox_disp_info.item.pszText != NULL, "got %p\n", g_editbox_disp_info.item.pszText);
memset(&item, 0, sizeof(item)); item.pszText = buffer; item.cchTextMax = sizeof(buffer); item.iItem = 0; item.iSubItem = 0; r = SendMessageA(hwnd, LVM_GETITEMTEXTA, 0, (LPARAM)&item); expect(lstrlenA(item.pszText), r); ok(strcmp(buffer, testitem2A) == 0, "got %s, expected %s\n", buffer, testitem2A); ok(!IsWindow(hwndedit), "Expected Edit window to be freed\n");
/* end edit without saving */ SetFocus(hwnd); hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0); flush_sequences(sequences, NUM_MSG_SEQUENCES); r = SendMessageA(hwndedit, WM_KEYDOWN, VK_ESCAPE, 0); expect(0, r); ok_sequence(sequences, PARENT_SEQ_INDEX, edit_end_nochange, "edit box - end edit, no change, escape", TRUE); /* end edit with saving */ SetFocus(hwnd); hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0); flush_sequences(sequences, NUM_MSG_SEQUENCES); r = SendMessageA(hwndedit, WM_KEYDOWN, VK_RETURN, 0); expect(0, r); ok_sequence(sequences, PARENT_SEQ_INDEX, edit_end_nochange, "edit box - end edit, no change, return", TRUE);
memset(&item, 0, sizeof(item)); item.pszText = buffer; item.cchTextMax = sizeof(buffer); item.iItem = 0; item.iSubItem = 0; r = SendMessageA(hwnd, LVM_GETITEMTEXTA, 0, (LPARAM)&item); expect(lstrlenA(item.pszText), r); ok(strcmp(buffer, testitem2A) == 0, "Expected item text to change\n");
/* LVM_EDITLABEL with -1 destroys current edit */ hwndedit = (HWND)SendMessageA(hwnd, LVM_GETEDITCONTROL, 0, 0); ok(hwndedit == NULL, "Expected Edit window not to be created\n"); /* no edit present */ hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, -1, 0); ok(hwndedit == NULL, "Expected Edit window not to be created\n"); hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0); ok(IsWindow(hwndedit), "Expected Edit window to be created\n"); /* edit present */ ok(GetFocus() == hwndedit, "Expected Edit to be focused\n"); hwndedit2 = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, -1, 0); ok(hwndedit2 == NULL, "Expected Edit window not to be created\n"); ok(!IsWindow(hwndedit), "Expected Edit window to be destroyed\n"); ok(GetFocus() == hwnd, "Expected List to be focused\n"); /* check another negative value */ hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0); ok(IsWindow(hwndedit), "Expected Edit window to be created\n"); ok(GetFocus() == hwndedit, "Expected Edit to be focused\n"); hwndedit2 = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, -2, 0); ok(hwndedit2 == NULL, "Expected Edit window not to be created\n"); ok(!IsWindow(hwndedit), "Expected Edit window to be destroyed\n"); ok(GetFocus() == hwnd, "Expected List to be focused\n"); /* and value greater than max item index */ hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0); ok(IsWindow(hwndedit), "Expected Edit window to be created\n"); ok(GetFocus() == hwndedit, "Expected Edit to be focused\n"); r = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0); hwndedit2 = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, r, 0); ok(hwndedit2 == NULL, "Expected Edit window not to be created\n"); ok(!IsWindow(hwndedit), "Expected Edit window to be destroyed\n"); ok(GetFocus() == hwnd, "Expected List to be focused\n");
/* messaging tests */ SetFocus(hwnd); flush_sequences(sequences, NUM_MSG_SEQUENCES); blockEdit = FALSE; hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0); ok(IsWindow(hwndedit), "Expected Edit window to be created\n"); /* testing only sizing messages */ ok_sequence(sequences, EDITBOX_SEQ_INDEX, editbox_create_pos, "edit box create - sizing", FALSE);
/* WM_COMMAND with EN_KILLFOCUS isn't forwarded to parent */ SetFocus(hwnd); hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0); ok(IsWindow(hwndedit), "Expected Edit window to be created\n"); flush_sequences(sequences, NUM_MSG_SEQUENCES); r = SendMessageA(hwnd, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), (LPARAM)hwndedit); expect(0, r); ok_sequence(sequences, PARENT_SEQ_INDEX, edit_end_nochange, "edit box WM_COMMAND (EN_KILLFOCUS)", TRUE);
DestroyWindow(hwnd);}
static void test_notifyformat(void){ HWND hwnd, header; DWORD r;
hwnd = create_listview_control(LVS_REPORT); ok(hwnd != NULL, "failed to create a listview window\n");
/* CCM_GETUNICODEFORMAT == LVM_GETUNICODEFORMAT, CCM_SETUNICODEFORMAT == LVM_SETUNICODEFORMAT */ r = SendMessageA(hwnd, LVM_GETUNICODEFORMAT, 0, 0); expect(0, r); SendMessageA(hwnd, WM_NOTIFYFORMAT, 0, NF_QUERY); /* set */ r = SendMessageA(hwnd, LVM_SETUNICODEFORMAT, 1, 0); expect(0, r); r = SendMessageA(hwnd, LVM_GETUNICODEFORMAT, 0, 0); ok(r == 1, "Unexpected return value %d.\n", r); r = SendMessageA(hwnd, LVM_SETUNICODEFORMAT, 0, 0); expect(1, r); r = SendMessageA(hwnd, LVM_GETUNICODEFORMAT, 0, 0); expect(0, r);
DestroyWindow(hwnd);
/* test failure in parent WM_NOTIFYFORMAT */ notifyFormat = 0; hwnd = create_listview_control(LVS_REPORT); ok(hwnd != NULL, "failed to create a listview window\n"); header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); ok(IsWindow(header), "expected header to be created\n"); r = SendMessageA(hwnd, LVM_GETUNICODEFORMAT, 0, 0); expect(0, r); r = SendMessageA(header, HDM_GETUNICODEFORMAT, 0, 0); ok( r == 1, "Expected 1, got %d\n", r ); r = SendMessageA(hwnd, WM_NOTIFYFORMAT, 0, NF_QUERY); ok(r != 0, "Expected valid format\n");
notifyFormat = NFR_UNICODE; r = SendMessageA(hwnd, WM_NOTIFYFORMAT, 0, NF_REQUERY); expect(NFR_UNICODE, r); r = SendMessageA(hwnd, LVM_GETUNICODEFORMAT, 0, 0); expect(1, r); r = SendMessageA(header, HDM_GETUNICODEFORMAT, 0, 0); ok( r == 1, "Expected 1, got %d\n", r );
notifyFormat = NFR_ANSI; r = SendMessageA(hwnd, WM_NOTIFYFORMAT, 0, NF_REQUERY); expect(NFR_ANSI, r); r = SendMessageA(hwnd, LVM_GETUNICODEFORMAT, 0, 0); expect(0, r); r = SendMessageA(header, HDM_GETUNICODEFORMAT, 0, 0); ok( r == 1, "Expected 1, got %d\n", r );
DestroyWindow(hwnd);
hwndparentW = create_parent_window(TRUE); ok(IsWindow(hwndparentW), "Unicode parent creation failed\n"); if (!IsWindow(hwndparentW)) return;
notifyFormat = -1; hwnd = create_listview_controlW(LVS_REPORT, hwndparentW); ok(hwnd != NULL, "failed to create a listview window\n"); header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); ok(IsWindow(header), "expected header to be created\n"); r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0); expect(1, r); r = SendMessageA(header, HDM_GETUNICODEFORMAT, 0, 0); expect(1, r); DestroyWindow(hwnd); /* receiving error code defaulting to ansi */ notifyFormat = 0; hwnd = create_listview_controlW(LVS_REPORT, hwndparentW); ok(hwnd != NULL, "failed to create a listview window\n"); header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); ok(IsWindow(header), "expected header to be created\n"); r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0); expect(0, r); r = SendMessageA(header, HDM_GETUNICODEFORMAT, 0, 0); expect(1, r); DestroyWindow(hwnd); /* receiving ansi code from unicode window, use it */ notifyFormat = NFR_ANSI; hwnd = create_listview_controlW(LVS_REPORT, hwndparentW); ok(hwnd != NULL, "failed to create a listview window\n"); header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); ok(IsWindow(header), "expected header to be created\n"); r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0); expect(0, r); r = SendMessageA(header, HDM_GETUNICODEFORMAT, 0, 0); expect(1, r); DestroyWindow(hwnd); /* unicode listview with ansi parent window */ notifyFormat = -1; hwnd = create_listview_controlW(LVS_REPORT, hwndparent); ok(hwnd != NULL, "failed to create a listview window\n"); header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); ok(IsWindow(header), "expected header to be created\n"); r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0); expect(0, r); r = SendMessageA(header, HDM_GETUNICODEFORMAT, 0, 0); expect(1, r); DestroyWindow(hwnd); /* unicode listview with ansi parent window, return error code */ notifyFormat = 0; hwnd = create_listview_controlW(LVS_REPORT, hwndparent); ok(hwnd != NULL, "failed to create a listview window\n"); header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); ok(IsWindow(header), "expected header to be created\n"); r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0); expect(0, r); r = SendMessageA(header, HDM_GETUNICODEFORMAT, 0, 0); expect(1, r); DestroyWindow(hwnd);
DestroyWindow(hwndparentW);}
static void test_indentation(void){ HWND hwnd; LVITEMA item; DWORD r;
hwnd = create_listview_control(LVS_REPORT); ok(hwnd != NULL, "failed to create a listview window\n");
memset(&item, 0, sizeof(item)); item.mask = LVIF_INDENT; item.iItem = 0; item.iIndent = I_INDENTCALLBACK; r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item); expect(0, r);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
item.iItem = 0; item.mask = LVIF_INDENT; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item); expect(TRUE, r);
ok_sequence(sequences, PARENT_SEQ_INDEX, single_getdispinfo_parent_seq, "get indent dispinfo", FALSE);
/* Ask for iIndent with invalid subitem. */ flush_sequences(sequences, NUM_MSG_SEQUENCES);
memset(&item, 0, sizeof(item)); item.mask = LVIF_INDENT; item.iSubItem = 1; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item); ok(r, "Failed to get item.\n");
ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "get indent dispinfo 2", FALSE);
DestroyWindow(hwnd);}
static INT CALLBACK DummyCompareEx(LPARAM first, LPARAM second, LPARAM param){ return 0;}
static BOOL is_below_comctl_5(void){ HWND hwnd; BOOL ret;
hwnd = create_listview_control(LVS_REPORT); ok(hwnd != NULL, "failed to create a listview window\n"); insert_item(hwnd, 0);
ret = SendMessageA(hwnd, LVM_SORTITEMSEX, 0, (LPARAM)&DummyCompareEx);
DestroyWindow(hwnd);
return !ret;}
static void test_get_set_view(void){ HWND hwnd; DWORD ret; DWORD_PTR style;
/* test style->view mapping */ hwnd = create_listview_control(LVS_REPORT); ok(hwnd != NULL, "failed to create a listview window\n");
ret = SendMessageA(hwnd, LVM_GETVIEW, 0, 0); expect(LV_VIEW_DETAILS, ret);
style = GetWindowLongPtrA(hwnd, GWL_STYLE); /* LVS_ICON == 0 */ SetWindowLongPtrA(hwnd, GWL_STYLE, style & ~LVS_REPORT); ret = SendMessageA(hwnd, LVM_GETVIEW, 0, 0); expect(LV_VIEW_ICON, ret);
style = GetWindowLongPtrA(hwnd, GWL_STYLE); SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SMALLICON); ret = SendMessageA(hwnd, LVM_GETVIEW, 0, 0); expect(LV_VIEW_SMALLICON, ret);
style = GetWindowLongPtrA(hwnd, GWL_STYLE); SetWindowLongPtrA(hwnd, GWL_STYLE, (style & ~LVS_SMALLICON) | LVS_LIST); ret = SendMessageA(hwnd, LVM_GETVIEW, 0, 0); expect(LV_VIEW_LIST, ret);
/* switching view doesn't touch window style */ ret = SendMessageA(hwnd, LVM_SETVIEW, LV_VIEW_DETAILS, 0); expect(1, ret); style = GetWindowLongPtrA(hwnd, GWL_STYLE); ok(style & LVS_LIST, "Expected style to be preserved\n"); ret = SendMessageA(hwnd, LVM_SETVIEW, LV_VIEW_ICON, 0); expect(1, ret); style = GetWindowLongPtrA(hwnd, GWL_STYLE); ok(style & LVS_LIST, "Expected style to be preserved\n"); ret = SendMessageA(hwnd, LVM_SETVIEW, LV_VIEW_SMALLICON, 0); expect(1, ret); style = GetWindowLongPtrA(hwnd, GWL_STYLE); ok(style & LVS_LIST, "Expected style to be preserved\n");
/* now change window style to see if view is remapped */ style = GetWindowLongPtrA(hwnd, GWL_STYLE); SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SHOWSELALWAYS); ret = SendMessageA(hwnd, LVM_GETVIEW, 0, 0); expect(LV_VIEW_SMALLICON, ret);
DestroyWindow(hwnd);}
static void test_canceleditlabel(void){ HWND hwnd, hwndedit; DWORD ret; CHAR buff[10]; LVITEMA itema; static CHAR test[] = "test"; static const CHAR test1[] = "test1";
hwnd = create_listview_control(LVS_EDITLABELS | LVS_REPORT); ok(hwnd != NULL, "failed to create a listview window\n");
insert_item(hwnd, 0);
/* try without edit created */ flush_sequences(sequences, NUM_MSG_SEQUENCES); ret = SendMessageA(hwnd, LVM_CANCELEDITLABEL, 0, 0); expect(TRUE, ret); ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "cancel edit label without edit", FALSE);
/* cancel without data change */ SetFocus(hwnd); hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0); ok(IsWindow(hwndedit), "Expected edit control to be created\n"); ret = SendMessageA(hwnd, LVM_CANCELEDITLABEL, 0, 0); expect(TRUE, ret); ok(!IsWindow(hwndedit), "Expected edit control to be destroyed\n");
/* cancel after data change */ memset(&itema, 0, sizeof(itema)); itema.pszText = test; ret = SendMessageA(hwnd, LVM_SETITEMTEXTA, 0, (LPARAM)&itema); expect(TRUE, ret); SetFocus(hwnd); hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0); ok(IsWindow(hwndedit), "Expected edit control to be created\n"); ret = SetWindowTextA(hwndedit, test1); expect(1, ret); ret = SendMessageA(hwnd, LVM_CANCELEDITLABEL, 0, 0); expect(TRUE, ret); ok(!IsWindow(hwndedit), "Expected edit control to be destroyed\n"); memset(&itema, 0, sizeof(itema)); itema.pszText = buff; itema.cchTextMax = ARRAY_SIZE(buff); ret = SendMessageA(hwnd, LVM_GETITEMTEXTA, 0, (LPARAM)&itema); expect(5, ret); ok(strcmp(buff, test1) == 0, "Expected label text not to change\n");
DestroyWindow(hwnd);}
static void test_mapidindex(void){ HWND hwnd; INT ret;
/* LVM_MAPINDEXTOID unsupported with LVS_OWNERDATA */ hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT); ok(hwnd != NULL, "failed to create a listview window\n"); insert_item(hwnd, 0); ret = SendMessageA(hwnd, LVM_MAPINDEXTOID, 0, 0); expect(-1, ret); DestroyWindow(hwnd);
hwnd = create_listview_control(LVS_REPORT); ok(hwnd != NULL, "failed to create a listview window\n");
/* LVM_MAPINDEXTOID with invalid index */ ret = SendMessageA(hwnd, LVM_MAPINDEXTOID, 0, 0); expect(-1, ret);
insert_item(hwnd, 0); insert_item(hwnd, 1);
ret = SendMessageA(hwnd, LVM_MAPINDEXTOID, -1, 0); expect(-1, ret); ret = SendMessageA(hwnd, LVM_MAPINDEXTOID, 2, 0); expect(-1, ret);
ret = SendMessageA(hwnd, LVM_MAPINDEXTOID, 0, 0); expect(0, ret); ret = SendMessageA(hwnd, LVM_MAPINDEXTOID, 1, 0); expect(1, ret); /* remove 0 indexed item, id retained */ SendMessageA(hwnd, LVM_DELETEITEM, 0, 0); ret = SendMessageA(hwnd, LVM_MAPINDEXTOID, 0, 0); expect(1, ret); /* new id starts from previous value */ insert_item(hwnd, 1); ret = SendMessageA(hwnd, LVM_MAPINDEXTOID, 1, 0); expect(2, ret);
/* get index by id */ ret = SendMessageA(hwnd, LVM_MAPIDTOINDEX, -1, 0); expect(-1, ret); ret = SendMessageA(hwnd, LVM_MAPIDTOINDEX, 0, 0); expect(-1, ret); ret = SendMessageA(hwnd, LVM_MAPIDTOINDEX, 1, 0); expect(0, ret); ret = SendMessageA(hwnd, LVM_MAPIDTOINDEX, 2, 0); expect(1, ret);
DestroyWindow(hwnd);}
static void test_getitemspacing(void){ HWND hwnd; DWORD ret; INT cx, cy; HIMAGELIST himl40, himl80;
cx = GetSystemMetrics(SM_CXICONSPACING) - GetSystemMetrics(SM_CXICON); cy = GetSystemMetrics(SM_CYICONSPACING) - GetSystemMetrics(SM_CYICON);
/* LVS_ICON */ hwnd = create_listview_control(LVS_ICON); ret = SendMessageA(hwnd, LVM_GETITEMSPACING, FALSE, 0); expect(cx, LOWORD(ret)); expect(cy, HIWORD(ret));
/* now try with icons */ himl40 = pImageList_Create(40, 40, 0, 4, 4); ok(himl40 != NULL, "failed to create imagelist\n"); himl80 = pImageList_Create(80, 80, 0, 4, 4); ok(himl80 != NULL, "failed to create imagelist\n"); ret = SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)himl40); expect(0, ret);
ret = SendMessageA(hwnd, LVM_GETITEMSPACING, FALSE, 0); /* spacing + icon size returned */ expect(cx + 40, LOWORD(ret)); expect(cy + 40, HIWORD(ret)); /* try changing icon size */ SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)himl80);
ret = SendMessageA(hwnd, LVM_GETITEMSPACING, FALSE, 0); /* spacing + icon size returned */ expect(cx + 80, LOWORD(ret)); expect(cy + 80, HIWORD(ret));
/* set own icon spacing */ ret = SendMessageA(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(100, 100)); expect(cx + 80, LOWORD(ret)); expect(cy + 80, HIWORD(ret));
ret = SendMessageA(hwnd, LVM_GETITEMSPACING, FALSE, 0); /* set size returned */ expect(100, LOWORD(ret)); expect(100, HIWORD(ret));
/* now change image list - icon spacing should be unaffected */ SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)himl40);
ret = SendMessageA(hwnd, LVM_GETITEMSPACING, FALSE, 0); /* set size returned */ expect(100, LOWORD(ret)); expect(100, HIWORD(ret));
/* spacing = 0 - keep previous value */ ret = SendMessageA(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(0, -1)); expect(100, LOWORD(ret)); expect(100, HIWORD(ret));
ret = SendMessageA(hwnd, LVM_GETITEMSPACING, FALSE, 0); expect(100, LOWORD(ret));
expect(0xFFFF, HIWORD(ret));
if (sizeof(void*) == 8) { /* NOTE: -1 is not treated the same as (DWORD)-1 by 64bit listview */ ret = SendMessageA(hwnd, LVM_SETICONSPACING, 0, (DWORD)-1); expect(100, LOWORD(ret)); expect(0xFFFF, HIWORD(ret));
ret = SendMessageA(hwnd, LVM_SETICONSPACING, 0, -1); expect(0xFFFF, LOWORD(ret)); expect(0xFFFF, HIWORD(ret)); } else { ret = SendMessageA(hwnd, LVM_SETICONSPACING, 0, -1); expect(100, LOWORD(ret)); expect(0xFFFF, HIWORD(ret)); } ret = SendMessageA(hwnd, LVM_GETITEMSPACING, FALSE, 0); /* spacing + icon size returned */ expect(cx + 40, LOWORD(ret)); expect(cy + 40, HIWORD(ret));
SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_NORMAL, 0); pImageList_Destroy(himl80); DestroyWindow(hwnd); /* LVS_SMALLICON */ hwnd = create_listview_control(LVS_SMALLICON); ret = SendMessageA(hwnd, LVM_GETITEMSPACING, FALSE, 0); expect(cx, LOWORD(ret)); expect(cy, HIWORD(ret));
/* spacing does not depend on selected view type */ ret = SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)himl40); expect(0, ret);
ret = SendMessageA(hwnd, LVM_GETITEMSPACING, FALSE, 0); /* spacing + icon size returned */ expect(cx + 40, LOWORD(ret)); expect(cy + 40, HIWORD(ret));
SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_NORMAL, 0); pImageList_Destroy(himl40); DestroyWindow(hwnd); /* LVS_REPORT */ hwnd = create_listview_control(LVS_REPORT); ret = SendMessageA(hwnd, LVM_GETITEMSPACING, FALSE, 0); expect(cx, LOWORD(ret)); expect(cy, HIWORD(ret));
DestroyWindow(hwnd); /* LVS_LIST */ hwnd = create_listview_control(LVS_LIST); ret = SendMessageA(hwnd, LVM_GETITEMSPACING, FALSE, 0); expect(cx, LOWORD(ret)); expect(cy, HIWORD(ret));
DestroyWindow(hwnd);}
static INT get_current_font_height(HWND listview){ TEXTMETRICA tm; HFONT hfont; HWND hwnd; HDC hdc;
hwnd = (HWND)SendMessageA(listview, LVM_GETHEADER, 0, 0); if (!hwnd) hwnd = listview;
hfont = (HFONT)SendMessageA(hwnd, WM_GETFONT, 0, 0); if (!hfont) { hdc = GetDC(hwnd); GetTextMetricsA(hdc, &tm); ReleaseDC(hwnd, hdc); } else { HFONT oldfont;
hdc = GetDC(0); oldfont = SelectObject(hdc, hfont); GetTextMetricsA(hdc, &tm); SelectObject(hdc, oldfont); ReleaseDC(0, hdc); }
return tm.tmHeight;}
static void test_getcolumnwidth(void){ HWND hwnd; INT ret; DWORD_PTR style; LVCOLUMNA col; LVITEMA itema; INT height;
/* default column width */ hwnd = create_listview_control(LVS_ICON); ret = SendMessageA(hwnd, LVM_GETCOLUMNWIDTH, 0, 0); expect(0, ret); style = GetWindowLongA(hwnd, GWL_STYLE); SetWindowLongA(hwnd, GWL_STYLE, style | LVS_LIST); ret = SendMessageA(hwnd, LVM_GETCOLUMNWIDTH, 0, 0); todo_wine expect(8, ret); style = GetWindowLongA(hwnd, GWL_STYLE) & ~LVS_LIST; SetWindowLongA(hwnd, GWL_STYLE, style | LVS_REPORT); col.mask = 0; ret = SendMessageA(hwnd, LVM_INSERTCOLUMNA, 0, (LPARAM)&col); expect(0, ret); ret = SendMessageA(hwnd, LVM_GETCOLUMNWIDTH, 0, 0); expect(10, ret); DestroyWindow(hwnd);
/* default column width with item added */ hwnd = create_listview_control(LVS_LIST); memset(&itema, 0, sizeof(itema)); ret = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&itema); ok(!ret, "got %d\n", ret); ret = SendMessageA(hwnd, LVM_GETCOLUMNWIDTH, 0, 0); height = get_current_font_height(hwnd); ok((ret / height) >= 6, "got width %d, height %d\n", ret, height); DestroyWindow(hwnd);}
static void test_scrollnotify(void){ HWND hwnd; DWORD ret;
hwnd = create_listview_control(LVS_REPORT);
insert_column(hwnd, 0); insert_column(hwnd, 1); insert_item(hwnd, 0);
/* make it scrollable - resize */ ret = SendMessageA(hwnd, LVM_SETCOLUMNWIDTH, 0, MAKELPARAM(100, 0)); expect(TRUE, ret); ret = SendMessageA(hwnd, LVM_SETCOLUMNWIDTH, 1, MAKELPARAM(100, 0)); expect(TRUE, ret);
/* try with dummy call */ flush_sequences(sequences, NUM_MSG_SEQUENCES); ret = SendMessageA(hwnd, LVM_SCROLL, 0, 0); expect(TRUE, ret); ok_sequence(sequences, PARENT_SEQ_INDEX, scroll_parent_seq, "scroll notify 1", TRUE);
flush_sequences(sequences, NUM_MSG_SEQUENCES); ret = SendMessageA(hwnd, LVM_SCROLL, 1, 0); expect(TRUE, ret); ok_sequence(sequences, PARENT_SEQ_INDEX, scroll_parent_seq, "scroll notify 2", TRUE);
flush_sequences(sequences, NUM_MSG_SEQUENCES); ret = SendMessageA(hwnd, LVM_SCROLL, 1, 1); expect(TRUE, ret); ok_sequence(sequences, PARENT_SEQ_INDEX, scroll_parent_seq, "scroll notify 3", TRUE);
DestroyWindow(hwnd);}
static void test_LVS_EX_TRANSPARENTBKGND(void){ HWND hwnd; DWORD ret; HDC hdc;
hwnd = create_listview_control(LVS_REPORT);
ret = SendMessageA(hwnd, LVM_SETBKCOLOR, 0, RGB(0, 0, 0)); expect(TRUE, ret);
SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_TRANSPARENTBKGND, LVS_EX_TRANSPARENTBKGND);
ret = SendMessageA(hwnd, LVM_GETBKCOLOR, 0, 0); if (ret != CLR_NONE) { win_skip("LVS_EX_TRANSPARENTBKGND unsupported\n"); DestroyWindow(hwnd); return; }
/* try to set some back color and check this style bit */ ret = SendMessageA(hwnd, LVM_SETBKCOLOR, 0, RGB(0, 0, 0)); expect(TRUE, ret); ret = SendMessageA(hwnd, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0); ok(!(ret & LVS_EX_TRANSPARENTBKGND), "Expected LVS_EX_TRANSPARENTBKGND to unset\n");
/* now test what this style actually does */ SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_TRANSPARENTBKGND, LVS_EX_TRANSPARENTBKGND);
hdc = GetWindowDC(hwndparent);
flush_sequences(sequences, NUM_MSG_SEQUENCES); SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0); ok_sequence(sequences, PARENT_SEQ_INDEX, lvs_ex_transparentbkgnd_seq, "LVS_EX_TRANSPARENTBKGND parent", FALSE);
ReleaseDC(hwndparent, hdc);
DestroyWindow(hwnd);}
static void test_approximate_viewrect(void){ static CHAR test[] = "abracadabra, a very long item label"; DWORD item_width, item_height, header_height; static CHAR column_header[] = "Header"; unsigned const column_width = 100; DWORD ret, item_count; HIMAGELIST himl; LVITEMA itema; LVCOLUMNA col; HBITMAP hbmp; HWND hwnd;
/* LVS_ICON */ hwnd = create_listview_control(LVS_ICON); himl = pImageList_Create(40, 40, 0, 4, 4); ok(himl != NULL, "failed to create imagelist\n"); hbmp = CreateBitmap(40, 40, 1, 1, NULL); ok(hbmp != NULL, "failed to create bitmap\n"); ret = pImageList_Add(himl, hbmp, 0); expect(0, ret); ret = SendMessageA(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)himl); expect(0, ret);
itema.mask = LVIF_IMAGE; itema.iImage = 0; itema.iItem = 0; itema.iSubItem = 0; ret = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&itema); expect(0, ret);
ret = SendMessageA(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(75, 75)); ok(ret != 0, "Unexpected return value %#x.\n", ret);
ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 11, MAKELPARAM(100,100)); expect(MAKELONG(77,827), ret);
ret = SendMessageA(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(50, 50)); ok(ret != 0, "got 0\n");
ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 11, MAKELPARAM(100,100)); expect(MAKELONG(102,302), ret);
ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, -1, MAKELPARAM(100,100)); expect(MAKELONG(52,52), ret);
itema.pszText = test; ret = SendMessageA(hwnd, LVM_SETITEMTEXTA, 0, (LPARAM)&itema); expect(TRUE, ret); ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, -1, MAKELPARAM(100,100)); expect(MAKELONG(52,52), ret);
ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 0, MAKELPARAM(100,100)); expect(MAKELONG(52,2), ret); ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 1, MAKELPARAM(100,100)); expect(MAKELONG(52,52), ret); ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 2, MAKELPARAM(100,100)); expect(MAKELONG(102,52), ret); ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 3, MAKELPARAM(100,100)); expect(MAKELONG(102,102), ret); ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 4, MAKELPARAM(100,100)); expect(MAKELONG(102,102), ret); ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 5, MAKELPARAM(100,100)); expect(MAKELONG(102,152), ret); ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 6, MAKELPARAM(100,100)); expect(MAKELONG(102,152), ret); ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 7, MAKELPARAM(160,100)); expect(MAKELONG(152,152), ret);
DestroyWindow(hwnd);
/* LVS_REPORT */ hwnd = create_listview_control(LVS_REPORT);
/* Empty control without columns */ ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 0, MAKELPARAM(100, 100));todo_wine ok(LOWORD(ret) == 0, "Unexpected width %d.\n", LOWORD(ret)); ok(HIWORD(ret) != 0, "Unexpected height %d.\n", HIWORD(ret));
ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 0, 0); ok(LOWORD(ret) == 0, "Unexpected width %d.\n", LOWORD(ret));todo_wine ok(HIWORD(ret) != 0, "Unexpected height %d.\n", HIWORD(ret));
header_height = HIWORD(ret);
ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 1, 0); ok(LOWORD(ret) == 0, "Unexpected width %d.\n", LOWORD(ret));todo_wine ok(HIWORD(ret) > header_height, "Unexpected height %d.\n", HIWORD(ret));
item_height = HIWORD(ret) - header_height;
ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, -2, 0); ok(LOWORD(ret) == 0, "Unexpected width %d.\n", LOWORD(ret)); ok(HIWORD(ret) == (header_height - 2 * item_height), "Unexpected height %d.\n", HIWORD(ret)) ;
ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, -1, 0); ok(LOWORD(ret) == 0, "Unexpected width %d.\n", LOWORD(ret)); ok(HIWORD(ret) == header_height, "Unexpected height.\n"); ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 2, 0); ok(LOWORD(ret) == 0, "Unexpected width %d.\n", LOWORD(ret)); ok(HIWORD(ret) == header_height + 2 * item_height, "Unexpected height %d.\n", HIWORD(ret));
/* Insert column */ col.mask = LVCF_TEXT | LVCF_WIDTH; col.pszText = column_header; col.cx = column_width; ret = SendMessageA(hwnd, LVM_INSERTCOLUMNA, 0, (LPARAM)&col); ok(ret == 0, "Unexpected return value %d.\n", ret);
/* Empty control with column */ ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 0, 0);todo_wine { ok(LOWORD(ret) >= column_width, "Unexpected width %d.\n", LOWORD(ret)); ok(HIWORD(ret) != 0, "Unexpected height %d.\n", HIWORD(ret));} header_height = HIWORD(ret); item_width = LOWORD(ret);
ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 1, 0); ok(LOWORD(ret) == item_width, "Unexpected width %d.\n", LOWORD(ret));todo_wine ok(HIWORD(ret) > header_height, "Unexpected height %d.\n", HIWORD(ret));
item_height = HIWORD(ret) - header_height;
ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, -2, 0); ok(LOWORD(ret) == item_width, "Unexpected width %d.\n", LOWORD(ret)); ok(HIWORD(ret) == header_height - 2 * item_height, "Unexpected height %d.\n", HIWORD(ret));
ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, -1, 0); ok(LOWORD(ret) == item_width, "Unexpected width %d.\n", LOWORD(ret)); ok(HIWORD(ret) == header_height, "Unexpected height %d.\n", HIWORD(ret));
ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 2, 0); ok(LOWORD(ret) == item_width, "Unexpected width %d.\n", LOWORD(ret)); ok(HIWORD(ret) == header_height + 2 * item_height, "Unexpected height %d.\n", HIWORD(ret));
for (item_count = 1; item_count <= 2; ++item_count) { itema.mask = LVIF_TEXT; itema.iItem = 0; itema.iSubItem = 0; itema.pszText = test; ret = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&itema); ok(ret == 0, "Unexpected return value %d.\n", ret);
ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 0, 0); ok(LOWORD(ret) >= column_width, "Unexpected width %d.\n", LOWORD(ret)); todo_wine ok(HIWORD(ret) != 0, "Unexpected height %d.\n", HIWORD(ret));
header_height = HIWORD(ret); item_width = LOWORD(ret);
ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 1, 0); ok(LOWORD(ret) == item_width, "Unexpected width %d, item %d\n", LOWORD(ret), item_count - 1); ok(HIWORD(ret) > header_height, "Unexpected height %d. item %d.\n", HIWORD(ret), item_count - 1);
item_height = HIWORD(ret) - header_height;
ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, -2, 0); ok(LOWORD(ret) == item_width, "Unexpected width %d.\n", LOWORD(ret)); todo_wine ok(HIWORD(ret) == header_height - 2 * item_height, "Unexpected height %d.\n", HIWORD(ret));
ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, -1, 0); ok(LOWORD(ret) == item_width, "Unexpected width %d.\n", LOWORD(ret)); ok(HIWORD(ret) == header_height + item_count * item_height, "Unexpected height %d.\n", HIWORD(ret));
ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 2, 0); ok(LOWORD(ret) == item_width, "Unexpected width %d.\n", LOWORD(ret)); ok(HIWORD(ret) == header_height + 2 * item_height, "Unexpected height %d.\n", HIWORD(ret));
ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 2, MAKELONG(item_width * 2, header_height + 3 * item_height)); ok(LOWORD(ret) == item_width, "Unexpected width %d.\n", LOWORD(ret)); ok(HIWORD(ret) == header_height + 2 * item_height, "Unexpected height %d.\n", HIWORD(ret));
ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, -2, MAKELONG(item_width * 2, 0)); ok(LOWORD(ret) == item_width, "Unexpected width %d.\n", LOWORD(ret)); todo_wine ok(HIWORD(ret) == header_height - 2 * item_height, "Unexpected height %d.\n", HIWORD(ret));
ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, -2, MAKELONG(-1, -1)); ok(LOWORD(ret) == item_width, "Unexpected width %d.\n", LOWORD(ret)); todo_wine ok(HIWORD(ret) == header_height - 2 * item_height, "Unexpected height %d.\n", HIWORD(ret)); }
DestroyWindow(hwnd);
}
static void test_finditem(void){ LVFINDINFOA fi; static char f[5]; HWND hwnd; INT r;
hwnd = create_listview_control(LVS_REPORT); insert_item(hwnd, 0);
memset(&fi, 0, sizeof(fi));
/* full string search, inserted text was "foo" */ strcpy(f, "foo"); fi.flags = LVFI_STRING; fi.psz = f; r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi); expect(0, r);
fi.flags = LVFI_STRING | LVFI_PARTIAL; r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi); expect(0, r);
fi.flags = LVFI_PARTIAL; r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi); expect(0, r);
/* partial string search, inserted text was "foo" */ strcpy(f, "fo"); fi.flags = LVFI_STRING | LVFI_PARTIAL; fi.psz = f; r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi); expect(0, r);
fi.flags = LVFI_STRING; r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi); expect(-1, r);
fi.flags = LVFI_PARTIAL; r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi); expect(0, r);
/* partial string search, part after start char */ strcpy(f, "oo"); fi.flags = LVFI_STRING | LVFI_PARTIAL; fi.psz = f; r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi); expect(-1, r);
/* try with LVFI_SUBSTRING */ strcpy(f, "fo"); fi.flags = LVFI_SUBSTRING; fi.psz = f; r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi); expect(0, r); strcpy(f, "f"); fi.flags = LVFI_SUBSTRING; fi.psz = f; r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi); expect(0, r); strcpy(f, "o"); fi.flags = LVFI_SUBSTRING; fi.psz = f; r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi); expect(-1, r);
strcpy(f, "o"); fi.flags = LVFI_SUBSTRING | LVFI_PARTIAL; fi.psz = f; r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi); expect(-1, r);
strcpy(f, "f"); fi.flags = LVFI_SUBSTRING | LVFI_STRING; fi.psz = f; r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi); expect(0, r);
fi.flags = LVFI_SUBSTRING | LVFI_PARTIAL; r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi); expect(0, r);
DestroyWindow(hwnd);}
static void test_LVS_EX_HEADERINALLVIEWS(void){ HWND hwnd, header; DWORD style;
hwnd = create_listview_control(LVS_ICON);
SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_HEADERINALLVIEWS, LVS_EX_HEADERINALLVIEWS);
header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); if (!IsWindow(header)) { win_skip("LVS_EX_HEADERINALLVIEWS unsupported\n"); DestroyWindow(hwnd); return; }
/* LVS_NOCOLUMNHEADER works as before */ style = GetWindowLongA(hwnd, GWL_STYLE); SetWindowLongW(hwnd, GWL_STYLE, style | LVS_NOCOLUMNHEADER); style = GetWindowLongA(header, GWL_STYLE); ok(style & HDS_HIDDEN, "Expected HDS_HIDDEN\n"); style = GetWindowLongA(hwnd, GWL_STYLE); SetWindowLongW(hwnd, GWL_STYLE, style & ~LVS_NOCOLUMNHEADER); style = GetWindowLongA(header, GWL_STYLE); ok(!(style & HDS_HIDDEN), "Expected HDS_HIDDEN to be unset\n");
/* try to remove style */ SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_HEADERINALLVIEWS, 0); header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); ok(IsWindow(header), "Expected header to be created\n"); style = GetWindowLongA(header, GWL_STYLE); ok(!(style & HDS_HIDDEN), "HDS_HIDDEN not expected\n");
DestroyWindow(hwnd);
/* check other styles */ hwnd = create_listview_control(LVS_LIST); SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_HEADERINALLVIEWS, LVS_EX_HEADERINALLVIEWS); header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); ok(IsWindow(header), "Expected header to be created\n"); DestroyWindow(hwnd);
hwnd = create_listview_control(LVS_SMALLICON); SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_HEADERINALLVIEWS, LVS_EX_HEADERINALLVIEWS); header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); ok(IsWindow(header), "Expected header to be created\n"); DestroyWindow(hwnd);
hwnd = create_listview_control(LVS_REPORT); SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_HEADERINALLVIEWS, LVS_EX_HEADERINALLVIEWS); header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); ok(IsWindow(header), "Expected header to be created\n"); DestroyWindow(hwnd);}
static void test_hover(void){ HWND hwnd, fg; DWORD r;
hwnd = create_listview_control(LVS_ICON); SetForegroundWindow(hwndparent); fg = GetForegroundWindow(); if (fg != hwndparent) { skip("Window is not in the foreground. Skipping hover tests.\n"); DestroyWindow(hwnd); return; }
/* test WM_MOUSEHOVER forwarding */ flush_sequences(sequences, NUM_MSG_SEQUENCES); r = SendMessageA(hwnd, WM_MOUSEHOVER, 0, 0); expect(0, r); ok_sequence(sequences, PARENT_SEQ_INDEX, hover_parent, "NM_HOVER allow test", TRUE); g_block_hover = TRUE; flush_sequences(sequences, NUM_MSG_SEQUENCES); r = SendMessageA(hwnd, WM_MOUSEHOVER, 0, 0); expect(0, r); ok_sequence(sequences, PARENT_SEQ_INDEX, hover_parent, "NM_HOVER block test", TRUE); g_block_hover = FALSE;
r = SendMessageA(hwnd, LVM_SETHOVERTIME, 0, 500); expect(HOVER_DEFAULT, r); r = SendMessageA(hwnd, LVM_GETHOVERTIME, 0, 0); expect(500, r);
DestroyWindow(hwnd);}
static void test_destroynotify(void){ HWND hwnd; BOOL ret;
hwnd = create_listview_control(LVS_REPORT); ok(hwnd != NULL, "failed to create listview window\n");
flush_sequences(sequences, NUM_MSG_SEQUENCES); DestroyWindow(hwnd); ok_sequence(sequences, COMBINED_SEQ_INDEX, listview_destroy, "check destroy order", FALSE);
/* same for ownerdata list */ hwnd = create_listview_control(LVS_REPORT|LVS_OWNERDATA); ok(hwnd != NULL, "failed to create listview window\n");
flush_sequences(sequences, NUM_MSG_SEQUENCES); DestroyWindow(hwnd); ok_sequence(sequences, COMBINED_SEQ_INDEX, listview_ownerdata_destroy, "check destroy order, ownerdata", FALSE);
hwnd = create_listview_control(LVS_REPORT|LVS_OWNERDATA); ok(hwnd != NULL, "failed to create listview window\n");
flush_sequences(sequences, NUM_MSG_SEQUENCES); ret = SendMessageA(hwnd, LVM_DELETEALLITEMS, 0, 0); ok(ret == TRUE, "got %d\n", ret); ok_sequence(sequences, COMBINED_SEQ_INDEX, listview_ownerdata_deleteall, "deleteall ownerdata", FALSE); DestroyWindow(hwnd);}
static void test_header_notification(void){ static char textA[] = "newtext"; HWND list, header; HDITEMA item; NMHEADERA nmh; LVCOLUMNA col; DWORD ret; BOOL r;
list = create_listview_control(LVS_REPORT); ok(list != NULL, "failed to create listview window\n");
memset(&col, 0, sizeof(col)); col.mask = LVCF_WIDTH; col.cx = 100; ret = SendMessageA(list, LVM_INSERTCOLUMNA, 0, (LPARAM)&col); expect(0, ret);
/* check list parent notification after header item changed, this test should be placed before header subclassing to avoid Listview -> Header messages to be logged */ flush_sequences(sequences, NUM_MSG_SEQUENCES);
col.mask = LVCF_TEXT; col.pszText = textA; r = SendMessageA(list, LVM_SETCOLUMNA, 0, (LPARAM)&col); expect(TRUE, r);
ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_header_changed_seq, "header notify, listview", FALSE); ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "header notify, parent", FALSE);
header = subclass_header(list);
ret = SendMessageA(header, HDM_GETITEMCOUNT, 0, 0); expect(1, ret);
memset(&item, 0, sizeof(item)); item.mask = HDI_WIDTH; ret = SendMessageA(header, HDM_GETITEMA, 0, (LPARAM)&item); expect(1, ret); expect(100, item.cxy);
nmh.hdr.hwndFrom = header; nmh.hdr.idFrom = GetWindowLongPtrA(header, GWLP_ID); nmh.hdr.code = HDN_ITEMCHANGEDA; nmh.iItem = 0; nmh.iButton = 0; item.mask = HDI_WIDTH; item.cxy = 50; nmh.pitem = &item; ret = SendMessageA(list, WM_NOTIFY, 0, (LPARAM)&nmh); expect(0, ret);
DestroyWindow(list);}
static void test_header_notification2(void){ static char textA[] = "newtext"; HWND list, header; HDITEMW itemW; NMHEADERW nmhdr; LVCOLUMNA col; DWORD ret; WCHAR buffer[100]; struct message parent_header_notify_seq[] = { { WM_NOTIFY, sent|id, 0, 0, 0 }, { 0 } };
list = create_listview_control(LVS_REPORT); ok(list != NULL, "failed to create listview window\n");
memset(&col, 0, sizeof(col)); col.mask = LVCF_WIDTH | LVCF_TEXT; col.cx = 100; col.pszText = textA; ret = SendMessageA(list, LVM_INSERTCOLUMNA, 0, (LPARAM)&col); expect(0, ret);
header = (HWND)SendMessageA(list, LVM_GETHEADER, 0, 0); ok(header != 0, "No header\n"); memset(&itemW, 0, sizeof(itemW)); itemW.mask = HDI_WIDTH | HDI_ORDER | HDI_TEXT; itemW.pszText = buffer; itemW.cchTextMax = ARRAY_SIZE(buffer); ret = SendMessageW(header, HDM_GETITEMW, 0, (LPARAM)&itemW); expect(1, ret);
nmhdr.hdr.hwndFrom = header; nmhdr.hdr.idFrom = GetWindowLongPtrW(header, GWLP_ID); nmhdr.iItem = 0; nmhdr.iButton = 0; nmhdr.pitem = &itemW;
flush_sequences(sequences, NUM_MSG_SEQUENCES); nmhdr.hdr.code = HDN_ITEMCHANGINGW; ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr); ok(ret == 0, "got %d\n", ret); parent_header_notify_seq[0].id = HDN_ITEMCHANGINGA; ok_sequence(sequences, PARENT_SEQ_INDEX, parent_header_notify_seq, "header notify, parent", TRUE); todo_wine ok(nmhdr.hdr.code == HDN_ITEMCHANGINGA, "Expected ANSI notification code\n"); flush_sequences(sequences, NUM_MSG_SEQUENCES); nmhdr.hdr.code = HDN_ITEMCHANGEDW; ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr); ok(ret == 0, "got %d\n", ret); parent_header_notify_seq[0].id = HDN_ITEMCHANGEDA; ok_sequence(sequences, PARENT_SEQ_INDEX, parent_header_notify_seq, "header notify, parent", TRUE); todo_wine ok(nmhdr.hdr.code == HDN_ITEMCHANGEDA, "Expected ANSI notification code\n"); /* HDN_ITEMCLICK sets focus to list, which generates messages we don't want to check */ SetFocus(list); flush_sequences(sequences, NUM_MSG_SEQUENCES); nmhdr.hdr.code = HDN_ITEMCLICKW; ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr); ok(ret == 0, "got %d\n", ret); ok_sequence(sequences, PARENT_SEQ_INDEX, parent_header_click_seq, "header notify, parent", FALSE); ok(nmhdr.hdr.code == HDN_ITEMCLICKA, "Expected ANSI notification code\n"); flush_sequences(sequences, NUM_MSG_SEQUENCES); nmhdr.hdr.code = HDN_ITEMDBLCLICKW; ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr); ok(ret == 0, "got %d\n", ret); ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "header notify, parent", FALSE); ok(nmhdr.hdr.code == HDN_ITEMDBLCLICKW, "Expected Unicode notification code\n"); flush_sequences(sequences, NUM_MSG_SEQUENCES); nmhdr.hdr.code = HDN_DIVIDERDBLCLICKW; ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr); ok(ret == 0, "got %d\n", ret); ok_sequence(sequences, PARENT_SEQ_INDEX, parent_header_divider_dclick_seq, "header notify, parent", TRUE); ok(nmhdr.hdr.code == HDN_DIVIDERDBLCLICKA, "Expected ANSI notification code\n"); flush_sequences(sequences, NUM_MSG_SEQUENCES); nmhdr.hdr.code = HDN_BEGINTRACKW; ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr); ok(ret == 0, "got %d\n", ret); ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "header notify, parent", FALSE); ok(nmhdr.hdr.code == HDN_BEGINTRACKW, "Expected Unicode notification code\n"); flush_sequences(sequences, NUM_MSG_SEQUENCES); nmhdr.hdr.code = HDN_ENDTRACKW; ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr); ok(ret == 0, "got %d\n", ret); parent_header_notify_seq[0].id = HDN_ENDTRACKA; ok_sequence(sequences, PARENT_SEQ_INDEX, parent_header_notify_seq, "header notify, parent", FALSE); ok(nmhdr.hdr.code == HDN_ENDTRACKA, "Expected ANSI notification code\n"); flush_sequences(sequences, NUM_MSG_SEQUENCES); nmhdr.hdr.code = HDN_TRACKW; ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr); ok(ret == 0, "got %d\n", ret); parent_header_notify_seq[0].id = HDN_TRACKA; ok_sequence(sequences, PARENT_SEQ_INDEX, parent_header_notify_seq, "header notify, parent", FALSE); ok(nmhdr.hdr.code == HDN_TRACKA, "Expected ANSI notification code\n"); flush_sequences(sequences, NUM_MSG_SEQUENCES); nmhdr.hdr.code = HDN_BEGINDRAG; ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr); ok(ret == 1, "got %d\n", ret); ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "header notify, parent", FALSE); flush_sequences(sequences, NUM_MSG_SEQUENCES); nmhdr.hdr.code = HDN_ENDDRAG; ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr); ok(ret == 0, "got %d\n", ret); parent_header_notify_seq[0].id = HDN_ENDDRAG; ok_sequence(sequences, PARENT_SEQ_INDEX, parent_header_notify_seq, "header notify, parent", FALSE); flush_sequences(sequences, NUM_MSG_SEQUENCES); nmhdr.hdr.code = HDN_FILTERCHANGE; ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr); ok(ret == 0, "got %d\n", ret); parent_header_notify_seq[0].id = HDN_FILTERCHANGE; parent_header_notify_seq[0].flags |= optional; /* NT4 does not send this message */ ok_sequence(sequences, PARENT_SEQ_INDEX, parent_header_notify_seq, "header notify, parent", FALSE); parent_header_notify_seq[0].flags &= ~optional; flush_sequences(sequences, NUM_MSG_SEQUENCES); nmhdr.hdr.code = HDN_BEGINFILTEREDIT; ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr); ok(ret == 0, "got %d\n", ret); ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "header notify, parent", FALSE); flush_sequences(sequences, NUM_MSG_SEQUENCES); nmhdr.hdr.code = HDN_ENDFILTEREDIT; ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr); ok(ret == 0, "got %d\n", ret); ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "header notify, parent", FALSE); flush_sequences(sequences, NUM_MSG_SEQUENCES); nmhdr.hdr.code = HDN_ITEMSTATEICONCLICK; ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr); ok(ret == 0, "got %d\n", ret); ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "header notify, parent", FALSE); flush_sequences(sequences, NUM_MSG_SEQUENCES); nmhdr.hdr.code = HDN_ITEMKEYDOWN; ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr); ok(ret == 0, "got %d\n", ret); ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "header notify, parent", FALSE);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
DestroyWindow(list);}
static void test_createdragimage(void){ HIMAGELIST himl; POINT pt; HWND list;
list = create_listview_control(LVS_ICON); ok(list != NULL, "failed to create listview window\n");
insert_item(list, 0);
/* NULL point */ himl = (HIMAGELIST)SendMessageA(list, LVM_CREATEDRAGIMAGE, 0, 0); ok(himl == NULL, "got %p\n", himl);
himl = (HIMAGELIST)SendMessageA(list, LVM_CREATEDRAGIMAGE, 0, (LPARAM)&pt); ok(himl != NULL, "got %p\n", himl); pImageList_Destroy(himl);
DestroyWindow(list);}
static void test_dispinfo(void){ static const char testA[] = "TEST"; WCHAR buff[10]; LVITEMA item; HWND hwnd; DWORD ret;
hwnd = create_listview_control(LVS_ICON); ok(hwnd != NULL, "failed to create listview window\n");
insert_item(hwnd, 0);
memset(&item, 0, sizeof(item)); item.pszText = LPSTR_TEXTCALLBACKA; ret = SendMessageA(hwnd, LVM_SETITEMTEXTA, 0, (LPARAM)&item); expect(1, ret);
g_disp_A_to_W = TRUE; item.pszText = (char*)buff; item.cchTextMax = ARRAY_SIZE(buff); ret = SendMessageA(hwnd, LVM_GETITEMTEXTA, 0, (LPARAM)&item); ok(ret == sizeof(testA)-1, "got %d, expected 4\n", ret); g_disp_A_to_W = FALSE;
ok(memcmp(item.pszText, testA, sizeof(testA)) == 0, "got %s, expected %s\n", item.pszText, testA);
DestroyWindow(hwnd);}
static void test_LVM_SETITEMTEXT(void){ static char testA[] = "TEST"; LVITEMA item; HWND hwnd; DWORD ret;
hwnd = create_listview_control(LVS_ICON); ok(hwnd != NULL, "failed to create listview window\n");
insert_item(hwnd, 0);
/* null item pointer */ ret = SendMessageA(hwnd, LVM_SETITEMTEXTA, 0, 0); expect(FALSE, ret);
ret = SendMessageA(hwnd, LVM_SETITEMTEXTW, 0, 0); expect(FALSE, ret);
/* index out of bounds */ item.pszText = testA; item.cchTextMax = 0; /* ignored */ item.iSubItem = 0;
ret = SendMessageA(hwnd, LVM_SETITEMTEXTA, 1, (LPARAM)&item); expect(FALSE, ret);
ret = SendMessageA(hwnd, LVM_SETITEMTEXTA, -1, (LPARAM)&item); expect(FALSE, ret);
ret = SendMessageA(hwnd, LVM_SETITEMTEXTA, 0, (LPARAM)&item); expect(TRUE, ret);
DestroyWindow(hwnd);}
static void test_LVM_REDRAWITEMS(void){ HWND list; DWORD ret;
list = create_listview_control(LVS_ICON); ok(list != NULL, "failed to create listview window\n");
ret = SendMessageA(list, LVM_REDRAWITEMS, 0, 0); expect(TRUE, ret);
insert_item(list, 0);
ret = SendMessageA(list, LVM_REDRAWITEMS, -1, 0); expect(TRUE, ret);
ret = SendMessageA(list, LVM_REDRAWITEMS, 0, -1); expect(TRUE, ret);
ret = SendMessageA(list, LVM_REDRAWITEMS, 0, 0); expect(TRUE, ret);
ret = SendMessageA(list, LVM_REDRAWITEMS, 0, 1); expect(TRUE, ret);
ret = SendMessageA(list, LVM_REDRAWITEMS, 0, 2); expect(TRUE, ret);
ret = SendMessageA(list, LVM_REDRAWITEMS, 1, 0); expect(TRUE, ret);
ret = SendMessageA(list, LVM_REDRAWITEMS, 2, 3); expect(TRUE, ret);
DestroyWindow(list);}
static void test_imagelists(void){ HWND hwnd, header; HIMAGELIST himl1, himl2, himl3; LRESULT ret;
himl1 = pImageList_Create(40, 40, 0, 4, 4); himl2 = pImageList_Create(40, 40, 0, 4, 4); himl3 = pImageList_Create(40, 40, 0, 4, 4); ok(himl1 != NULL, "Failed to create imagelist\n"); ok(himl2 != NULL, "Failed to create imagelist\n"); ok(himl3 != NULL, "Failed to create imagelist\n");
hwnd = create_listview_control(LVS_REPORT | LVS_SHAREIMAGELISTS); header = subclass_header(hwnd);
ok(header != NULL, "Expected header\n"); ret = SendMessageA(header, HDM_GETIMAGELIST, 0, 0); ok(ret == 0, "Expected no imagelist, got %p\n", (HIMAGELIST)ret);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
ret = SendMessageW(hwnd, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)himl1); ok(ret == 0, "Expected no imagelist, got %p\n", (HIMAGELIST)ret); ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_set_imagelist, "set normal image list", FALSE);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
ret = SendMessageW(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)himl2); ok(ret == 0, "Expected no imagelist, got %p\n", (HIMAGELIST)ret); ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_set_imagelist, "set state image list", TRUE);
ret = SendMessageA(header, HDM_GETIMAGELIST, 0, 0); ok(ret == 0, "Expected no imagelist, got %p\n", (HIMAGELIST)ret);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
ret = SendMessageW(hwnd, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)himl3); ok(ret == 0, "Expected no imagelist, got %p\n", (HIMAGELIST)ret); ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_header_set_imagelist, "set small image list", FALSE);
ret = SendMessageA(header, HDM_GETIMAGELIST, 0, 0); ok((HIMAGELIST)ret == himl3, "Expected imagelist %p, got %p\n", himl3, (HIMAGELIST)ret); DestroyWindow(hwnd);
hwnd = create_listview_control(WS_VISIBLE | LVS_ICON);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
ret = SendMessageW(hwnd, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)himl1); ok(ret == 0, "Expected no imagelist, got %p\n", (HIMAGELIST)ret); ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_set_imagelist, "set normal image list", FALSE);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
ret = SendMessageW(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)himl2); ok(ret == 0, "Expected no imagelist, got %p\n", (HIMAGELIST)ret); ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_set_imagelist, "set state image list", FALSE);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
ret = SendMessageW(hwnd, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)himl3); ok(ret == 0, "Expected no imagelist, got %p\n", (HIMAGELIST)ret); ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_set_imagelist, "set small image list", FALSE);
header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); ok(header == NULL, "Expected no header, got %p\n", header);
SetWindowLongPtrA(hwnd, GWL_STYLE, GetWindowLongPtrA(hwnd, GWL_STYLE) | LVS_REPORT);
header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); ok(header != NULL, "Expected header, got NULL\n");
ret = SendMessageA(header, HDM_GETIMAGELIST, 0, 0); ok((HIMAGELIST)ret == himl3, "Expected imagelist %p, got %p\n", himl3, (HIMAGELIST)ret);
DestroyWindow(hwnd);}
static void test_deleteitem(void){ LVITEMA item; UINT state; HWND hwnd; BOOL ret;
hwnd = create_listview_control(LVS_REPORT);
insert_item(hwnd, 0); insert_item(hwnd, 0); insert_item(hwnd, 0); insert_item(hwnd, 0); insert_item(hwnd, 0);
g_focus_test_LVN_DELETEITEM = TRUE;
/* delete focused item (not the last index) */ item.stateMask = LVIS_FOCUSED; item.state = LVIS_FOCUSED; ret = SendMessageA(hwnd, LVM_SETITEMSTATE, 2, (LPARAM)&item); ok(ret == TRUE, "got %d\n", ret); ret = SendMessageA(hwnd, LVM_DELETEITEM, 2, 0); ok(ret == TRUE, "got %d\n", ret); /* next item gets focus */ state = SendMessageA(hwnd, LVM_GETITEMSTATE, 2, LVIS_FOCUSED); ok(state == LVIS_FOCUSED, "got %x\n", state);
/* focus last item and delete it */ item.stateMask = LVIS_FOCUSED; item.state = LVIS_FOCUSED; ret = SendMessageA(hwnd, LVM_SETITEMSTATE, 3, (LPARAM)&item); ok(ret == TRUE, "got %d\n", ret); ret = SendMessageA(hwnd, LVM_DELETEITEM, 3, 0); ok(ret == TRUE, "got %d\n", ret); /* new last item gets focus */ state = SendMessageA(hwnd, LVM_GETITEMSTATE, 2, LVIS_FOCUSED); ok(state == LVIS_FOCUSED, "got %x\n", state);
/* focus first item and delete it */ item.stateMask = LVIS_FOCUSED; item.state = LVIS_FOCUSED; ret = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item); ok(ret == TRUE, "got %d\n", ret); ret = SendMessageA(hwnd, LVM_DELETEITEM, 0, 0); ok(ret == TRUE, "got %d\n", ret); /* new first item gets focus */ state = SendMessageA(hwnd, LVM_GETITEMSTATE, 0, LVIS_FOCUSED); ok(state == LVIS_FOCUSED, "got %x\n", state);
g_focus_test_LVN_DELETEITEM = FALSE;
DestroyWindow(hwnd);}
static void test_insertitem(void){ LVITEMA item; UINT state; HWND hwnd; INT ret;
hwnd = create_listview_control(LVS_REPORT);
/* insert item 0 focused */ item.mask = LVIF_STATE; item.state = LVIS_FOCUSED; item.stateMask = LVIS_FOCUSED; item.iItem = 0; item.iSubItem = 0; ret = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item); ok(ret == 0, "got %d\n", ret);
state = SendMessageA(hwnd, LVM_GETITEMSTATE, 0, LVIS_FOCUSED); ok(state == LVIS_FOCUSED, "got %x\n", state);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
/* insert item 1, focus shift */ item.mask = LVIF_STATE; item.state = LVIS_FOCUSED; item.stateMask = LVIS_FOCUSED; item.iItem = 1; item.iSubItem = 0; ret = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item); ok(ret == 1, "got %d\n", ret);
ok_sequence(sequences, PARENT_SEQ_INDEX, parent_insert_focused_seq, "insert focused", TRUE);
state = SendMessageA(hwnd, LVM_GETITEMSTATE, 1, LVIS_FOCUSED); ok(state == LVIS_FOCUSED, "got %x\n", state);
/* insert item 2, no focus shift */ item.mask = LVIF_STATE; item.state = 0; item.stateMask = LVIS_FOCUSED; item.iItem = 2; item.iSubItem = 0; ret = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item); ok(ret == 2, "got %d\n", ret);
state = SendMessageA(hwnd, LVM_GETITEMSTATE, 1, LVIS_FOCUSED); ok(state == LVIS_FOCUSED, "got %x\n", state);
DestroyWindow(hwnd);}
static void test_header_proc(void){ HWND hwnd, header, hdr; WNDPROC proc1, proc2;
hwnd = create_listview_control(LVS_REPORT);
header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); ok(header != NULL, "got %p\n", header);
hdr = CreateWindowExA(0, WC_HEADERA, NULL, WS_BORDER|WS_VISIBLE|HDS_BUTTONS|HDS_HORZ, 0, 0, 0, 0, NULL, NULL, NULL, NULL); ok(hdr != NULL, "got %p\n", hdr);
proc1 = (WNDPROC)GetWindowLongPtrW(header, GWLP_WNDPROC); proc2 = (WNDPROC)GetWindowLongPtrW(hdr, GWLP_WNDPROC); ok(proc1 == proc2, "got %p, expected %p\n", proc1, proc2);
DestroyWindow(hdr); DestroyWindow(hwnd);}
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 test_oneclickactivate(void){ TRACKMOUSEEVENT track; char item1[] = "item1"; LVITEMA item; HWND hwnd, fg; RECT rect; INT r; POINT orig_pos;
hwnd = CreateWindowExA(0, WC_LISTVIEWA, "foo", WS_VISIBLE|WS_CHILD|LVS_LIST, 10, 10, 100, 200, hwndparent, NULL, NULL, NULL); ok(hwnd != NULL, "failed to create listview window\n"); r = SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_ONECLICKACTIVATE); ok(r == 0, "should return zero\n");
SetForegroundWindow(hwndparent); flush_events(); fg = GetForegroundWindow(); if (fg != hwndparent) { skip("Window is not in the foreground. Skipping oneclickactivate tests.\n"); DestroyWindow(hwnd); return; }
item.mask = LVIF_TEXT; item.iItem = 0; item.iSubItem = 0; item.iImage = 0; item.pszText = item1; r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); ok(r == 0, "should not fail\n");
GetWindowRect(hwnd, &rect); GetCursorPos(&orig_pos); SetCursorPos(rect.left+5, rect.top+5); flush_events(); r = SendMessageA(hwnd, WM_MOUSEMOVE, MAKELONG(1, 1), 0); expect(0, r);
track.cbSize = sizeof(track); track.dwFlags = TME_QUERY; p_TrackMouseEvent(&track); ok(track.hwndTrack == hwnd, "hwndTrack != hwnd\n"); ok(track.dwFlags == TME_LEAVE, "dwFlags = %x\n", track.dwFlags);
r = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0); expect(0, r); r = SendMessageA(hwnd, WM_MOUSEHOVER, MAKELONG(1, 1), 0); expect(0, r); r = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0); expect(1, r);
DestroyWindow(hwnd); SetCursorPos(orig_pos.x, orig_pos.y);}
static void test_callback_mask(void){ LVITEMA item; DWORD mask; HWND hwnd; BOOL ret;
hwnd = create_listview_control(LVS_REPORT);
ret = SendMessageA(hwnd, LVM_SETCALLBACKMASK, ~0u, 0); ok(ret, "got %d\n", ret);
ret = SendMessageA(hwnd, LVM_SETCALLBACKMASK, ~0u, 1); ok(ret, "got %d\n", ret);
mask = SendMessageA(hwnd, LVM_GETCALLBACKMASK, 0, 0); ok(mask == ~0u, "got 0x%08x\n", mask);
/* Ask for state, invalid subitem. */ insert_item(hwnd, 0);
ret = SendMessageA(hwnd, LVM_SETCALLBACKMASK, LVIS_FOCUSED, 0); ok(ret, "Failed to set callback mask.\n");
flush_sequences(sequences, NUM_MSG_SEQUENCES);
memset(&item, 0, sizeof(item)); item.iSubItem = 1; item.mask = LVIF_STATE; item.stateMask = LVIS_SELECTED; ret = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item); ok(ret, "Failed to get item data.\n");
memset(&item, 0, sizeof(item)); item.mask = LVIF_STATE; item.stateMask = LVIS_SELECTED; ret = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item); ok(ret, "Failed to get item data.\n");
ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "parent seq, callback mask/invalid subitem 1", TRUE);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
memset(&item, 0, sizeof(item)); memset(&g_itema, 0, sizeof(g_itema)); item.iSubItem = 1; item.mask = LVIF_STATE; item.stateMask = LVIS_FOCUSED | LVIS_SELECTED; ret = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item); ok(ret, "Failed to get item data.\n"); ok(g_itema.iSubItem == 1, "Unexpected LVN_DISPINFO subitem %d.\n", g_itema.iSubItem); ok(g_itema.stateMask == LVIS_FOCUSED, "Unexpected state mask %#x.\n", g_itema.stateMask);
ok_sequence(sequences, PARENT_SEQ_INDEX, single_getdispinfo_parent_seq, "parent seq, callback mask/invalid subitem 2", FALSE);
DestroyWindow(hwnd);
/* LVS_OWNERDATA, mask LVIS_FOCUSED */ hwnd = create_listview_control(LVS_REPORT | LVS_OWNERDATA);
mask = SendMessageA(hwnd, LVM_GETCALLBACKMASK, 0, 0); ok(mask == 0, "Unexpected callback mask %#x.\n", mask);
ret = SendMessageA(hwnd, LVM_SETCALLBACKMASK, LVIS_FOCUSED, 0); ok(ret, "Failed to set callback mask, %d\n", ret);
mask = SendMessageA(hwnd, LVM_GETCALLBACKMASK, 0, 0); ok(mask == LVIS_FOCUSED, "Unexpected callback mask %#x.\n", mask);
ret = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0); ok(ret, "Failed to set item count.\n");
ret = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); ok(ret == -1, "Unexpected selection mark, %d\n", ret);
item.stateMask = LVIS_FOCUSED; item.state = LVIS_FOCUSED; ret = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item); ok(ret, "Failed to set item state.\n");
flush_sequences(sequences, NUM_MSG_SEQUENCES);
ret = SendMessageA(hwnd, LVM_GETNEXTITEM, -1, LVNI_FOCUSED);todo_wine ok(ret == 0, "Unexpected focused item, ret %d\n", ret);
ret = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0);todo_wine ok(ret == 0, "Unexpected selection mark, %d\n", ret);
ret = SendMessageA(hwnd, LVM_SETITEMCOUNT, 0, 0); ok(ret, "Failed to set item count.\n");
ret = SendMessageA(hwnd, LVM_GETNEXTITEM, -1, LVNI_FOCUSED); ok(ret == -1, "Unexpected focused item, ret %d\n", ret);
ret = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); ok(ret == -1, "Unexpected selection mark, %d\n", ret);
ret = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0); ok(ret, "Failed to set item count.\n");
ret = SendMessageA(hwnd, LVM_GETNEXTITEM, -1, LVNI_FOCUSED); ok(ret == -1, "Unexpected focused item, ret %d\n", ret);
ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "parent seq, owner data/focus 1", FALSE);
/* LVS_OWNDERDATA, empty mask */ ret = SendMessageA(hwnd, LVM_SETCALLBACKMASK, 0, 0); ok(ret, "Failed to set callback mask, %d\n", ret);
ret = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0); ok(ret, "Failed to set item count.\n");
ret = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); ok(ret == -1, "Unexpected selection mark, %d\n", ret);
item.stateMask = LVIS_FOCUSED; item.state = LVIS_FOCUSED; ret = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item); ok(ret, "Failed to set item state.\n");
ret = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); ok(ret == 0, "Unexpected selection mark, %d\n", ret);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
ret = SendMessageA(hwnd, LVM_GETNEXTITEM, -1, LVNI_FOCUSED); ok(ret == 0, "Unexpected focused item, ret %d\n", ret);
ret = SendMessageA(hwnd, LVM_SETITEMCOUNT, 0, 0); ok(ret, "Failed to set item count.\n");
ret = SendMessageA(hwnd, LVM_GETNEXTITEM, -1, LVNI_FOCUSED); ok(ret == -1, "Unexpected focused item, ret %d\n", ret);
ret = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0);todo_wine ok(ret == -1, "Unexpected selection mark, %d\n", ret);
ret = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0); ok(ret, "Failed to set item count.\n");
ret = SendMessageA(hwnd, LVM_GETNEXTITEM, -1, LVNI_FOCUSED); ok(ret == -1, "Unexpected focused item, ret %d\n", ret);
ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "parent seq, owner data/focus 2", FALSE);
/* 2 items, focus on index 0, reduce to 1 item. */ flush_sequences(sequences, NUM_MSG_SEQUENCES);
ret = SendMessageA(hwnd, LVM_SETITEMCOUNT, 2, 0); ok(ret, "Failed to set item count.\n");
ret = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item); ok(ret, "Failed to set item state.\n");
ret = SendMessageA(hwnd, LVM_GETNEXTITEM, -1, LVNI_FOCUSED); ok(ret == 0, "Unexpected focused item, ret %d\n", ret);
ret = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0); ok(ret, "Failed to set item count.\n");
ret = SendMessageA(hwnd, LVM_GETNEXTITEM, -1, LVNI_FOCUSED); ok(ret == 0, "Unexpected focused item, ret %d\n", ret);
ok_sequence(sequences, PARENT_SEQ_INDEX, parent_focus_change_ownerdata_seq, "parent seq, owner data/focus 3", TRUE);
DestroyWindow(hwnd);}
static void test_state_image(void){ static const DWORD styles[] = { LVS_ICON, LVS_REPORT, LVS_SMALLICON, LVS_LIST, }; int i;
for (i = 0; i < ARRAY_SIZE(styles); i++) { static char text[] = "Item"; static char subtext[] = "Subitem"; char buff[16]; LVITEMA item; HWND hwnd; int r;
hwnd = create_listview_control(styles[i]);
insert_column(hwnd, 0); insert_column(hwnd, 1);
item.mask = LVIF_TEXT | LVIF_PARAM; item.iItem = 0; item.iSubItem = 0; item.pszText = text; item.lParam = 123456; r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item); ok(r == 0, "Failed to insert an item.\n");
item.mask = LVIF_STATE; item.state = INDEXTOSTATEIMAGEMASK(1) | LVIS_SELECTED | LVIS_FOCUSED; item.stateMask = LVIS_STATEIMAGEMASK | LVIS_SELECTED | LVIS_FOCUSED; item.iItem = 0; item.iSubItem = 0; r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item); ok(r, "Failed to set item state.\n");
item.mask = LVIF_TEXT; item.iItem = 0; item.iSubItem = 1; item.pszText = subtext; r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item); ok(r, "Failed to set subitem text.\n");
item.mask = LVIF_STATE | LVIF_PARAM; item.stateMask = ~0u; item.state = 0; item.iItem = 0; item.iSubItem = 0; item.lParam = 0; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item); ok(r, "Failed to get item state.\n"); ok(item.state == (INDEXTOSTATEIMAGEMASK(1) | LVIS_SELECTED | LVIS_FOCUSED), "Unexpected item state %#x.\n", item.state); ok(item.lParam == 123456, "Unexpected lParam %ld.\n", item.lParam);
item.mask = 0; item.stateMask = ~0u; item.state = INDEXTOSTATEIMAGEMASK(2); item.iItem = 0; item.iSubItem = 1; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item); ok(r, "Failed to get subitem state.\n"); ok(item.state == INDEXTOSTATEIMAGEMASK(2), "Unexpected state %#x.\n", item.state);
item.mask = LVIF_STATE | LVIF_PARAM; item.stateMask = ~0u; item.state = INDEXTOSTATEIMAGEMASK(2); item.iItem = 0; item.iSubItem = 1; item.lParam = 0; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item); ok(r, "Failed to get subitem state.\n"); ok(item.state == 0, "Unexpected state %#x.\n", item.state); ok(item.lParam == 123456, "Unexpected lParam %ld.\n", item.lParam);
item.mask = LVIF_STATE; item.stateMask = LVIS_FOCUSED; item.state = 0; item.iItem = 0; item.iSubItem = 1; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item); ok(r, "Failed to get subitem state.\n"); ok(item.state == 0, "Unexpected state %#x.\n", item.state);
item.mask = LVIF_STATE; item.stateMask = ~0u; item.state = INDEXTOSTATEIMAGEMASK(2); item.iItem = 0; item.iSubItem = 2; r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item); ok(r, "Failed to get subitem state.\n"); ok(item.state == 0, "Unexpected state %#x.\n", item.state);
item.mask = LVIF_TEXT; item.iItem = 0; item.iSubItem = 1; item.pszText = buff; item.cchTextMax = sizeof(buff); r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item); ok(r, "Failed to get subitem text %d.\n", r); ok(!strcmp(buff, subtext), "Unexpected subitem text %s.\n", buff);
DestroyWindow(hwnd); }}
static void test_LVSCW_AUTOSIZE(void){ int width, width2; HWND hwnd; BOOL ret;
hwnd = create_listview_control(LVS_REPORT); ok(hwnd != NULL, "failed to create a listview window\n");
insert_column(hwnd, 0); insert_column(hwnd, 1); insert_item(hwnd, 0);
ret = SendMessageA(hwnd, LVM_SETCOLUMNWIDTH, 0, LVSCW_AUTOSIZE); ok(ret, "Failed to set column width.\n");
width = SendMessageA(hwnd, LVM_GETCOLUMNWIDTH, 0, 0); ok(width > 0, "Unexpected column width %d.\n", width);
/* Turn on checkboxes. */ ret = SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES); ok(ret == 0, "Unexpected previous extended style.\n");
ret = SendMessageA(hwnd, LVM_SETCOLUMNWIDTH, 0, LVSCW_AUTOSIZE); ok(ret, "Failed to set column width.\n");
width2 = SendMessageA(hwnd, LVM_GETCOLUMNWIDTH, 0, 0); ok(width2 > 0, "Unexpected column width %d.\n", width2); ok(width2 > width, "Expected increased column width.\n");
/* Turn off checkboxes. */ ret = SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, 0); ok(ret == LVS_EX_CHECKBOXES, "Unexpected previous extended style.\n");
ret = SendMessageA(hwnd, LVM_SETCOLUMNWIDTH, 0, LVSCW_AUTOSIZE); ok(ret, "Failed to set column width.\n");
width = SendMessageA(hwnd, LVM_GETCOLUMNWIDTH, 0, 0); ok(width > 0, "Unexpected column width %d.\n", width2); ok(width2 > width, "Expected reduced column width.\n");
DestroyWindow(hwnd);}
static void test_LVN_ENDLABELEDIT(void){ WCHAR text[] = {'l','a','l','a',0}; HWND hwnd, hwndedit; LVITEMW item = {0}; DWORD ret;
hwnd = create_listview_control(LVS_REPORT | LVS_EDITLABELS);
insert_column(hwnd, 0);
item.mask = LVIF_TEXT; item.pszText = text; SendMessageW(hwnd, LVM_INSERTITEMW, 0, (LPARAM)&item);
/* Test normal editing */ SetFocus(hwnd); hwndedit = (HWND)SendMessageW(hwnd, LVM_EDITLABELW, 0, 0); ok(hwndedit != NULL, "Failed to get edit control.\n");
ret = SendMessageA(hwndedit, WM_SETTEXT, 0, (LPARAM)"test"); ok(ret, "Failed to set edit text.\n");
flush_sequences(sequences, NUM_MSG_SEQUENCES);
ret = SendMessageA(hwndedit, WM_KEYDOWN, VK_RETURN, 0); ok_sequence(sequences, PARENT_SEQ_INDEX, listview_end_label_edit, "Label edit", FALSE);
/* Test editing with kill focus */ SetFocus(hwnd); hwndedit = (HWND)SendMessageW(hwnd, LVM_EDITLABELW, 0, 0); ok(hwndedit != NULL, "Failed to get edit control.\n");
ret = SendMessageA(hwndedit, WM_SETTEXT, 0, (LPARAM)"test2"); ok(ret, "Failed to set edit text.\n");
flush_sequences(sequences, NUM_MSG_SEQUENCES);
g_WM_KILLFOCUS_on_LVN_ENDLABELEDIT = TRUE; ret = SendMessageA(hwndedit, WM_KEYDOWN, VK_RETURN, 0); g_WM_KILLFOCUS_on_LVN_ENDLABELEDIT = FALSE;
ok_sequence(sequences, PARENT_SEQ_INDEX, listview_end_label_edit_kill_focus, "Label edit, kill focus", FALSE); ok(GetFocus() == hwnd, "Unexpected focused window.\n");
flush_sequences(sequences, NUM_MSG_SEQUENCES);
DestroyWindow(hwnd);}
static LRESULT CALLBACK create_item_height_wndproc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){ if (msg == WM_CREATE) return 0;
return CallWindowProcA(listviewWndProc, hwnd, msg, wParam, lParam);}
static void test_LVM_GETCOUNTPERPAGE(void){ static const DWORD styles[] = { LVS_ICON, LVS_LIST, LVS_REPORT, LVS_SMALLICON }; unsigned int i, j; WNDCLASSEXA cls; ATOM class; HWND hwnd; BOOL ret;
cls.cbSize = sizeof(WNDCLASSEXA); ret = GetClassInfoExA(GetModuleHandleA(NULL), WC_LISTVIEWA, &cls); ok(ret, "Failed to get class info.\n"); listviewWndProc = cls.lpfnWndProc; cls.lpfnWndProc = create_item_height_wndproc; cls.lpszClassName = "CountPerPageClass"; class = RegisterClassExA(&cls); ok(class, "Failed to register class.\n");
for (i = 0; i < ARRAY_SIZE(styles); i++) { static char text[] = "item text"; LVITEMA item = { 0 }; UINT count, count2;
hwnd = create_listview_control(styles[i]); ok(hwnd != NULL, "Failed to create listview window.\n");
count = SendMessageA(hwnd, LVM_GETCOUNTPERPAGE, 0, 0); if (styles[i] == LVS_LIST || styles[i] == LVS_REPORT) ok(count > 0 || broken(styles[i] == LVS_LIST && count == 0), "%u: unexpected count %u.\n", i, count); else ok(count == 0, "%u: unexpected count %u.\n", i, count);
for (j = 0; j < 10; j++) { item.mask = LVIF_TEXT; item.pszText = text; SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item); }
count2 = SendMessageA(hwnd, LVM_GETCOUNTPERPAGE, 0, 0); if (styles[i] == LVS_LIST || styles[i] == LVS_REPORT) ok(count == count2, "%u: unexpected count %u.\n", i, count2); else ok(count2 == 10, "%u: unexpected count %u.\n", i, count2);
DestroyWindow(hwnd);
hwnd = CreateWindowA("CountPerPageClass", "Test", WS_VISIBLE | styles[i], 0, 0, 100, 100, NULL, NULL, GetModuleHandleA(NULL), 0); ok(hwnd != NULL, "Failed to create a window.\n");
count = SendMessageA(hwnd, LVM_GETCOUNTPERPAGE, 0, 0); ok(count == 0, "%u: unexpected count %u.\n", i, count);
DestroyWindow(hwnd); }
ret = UnregisterClassA("CountPerPageClass", NULL); ok(ret, "Failed to unregister test class.\n");}
static void test_item_state_change(void){ static const DWORD styles[] = { LVS_ICON, LVS_LIST, LVS_REPORT, LVS_SMALLICON }; LVITEMA item; HWND hwnd; DWORD res; int i;
for (i = 0; i < ARRAY_SIZE(styles); i++) { hwnd = create_listview_control(styles[i]);
insert_item(hwnd, 0);
/* LVM_SETITEMSTATE with mask */ memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview)); memset(&item, 0, sizeof(item)); item.mask = LVIF_STATE; item.stateMask = LVIS_SELECTED; item.state = LVIS_SELECTED; res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item); ok(res, "Failed to set item state.\n");
ok(g_nmlistview.iItem == item.iItem, "Unexpected item %d.\n", g_nmlistview.iItem); ok(g_nmlistview.iSubItem == item.iSubItem, "Unexpected subitem %d.\n", g_nmlistview.iSubItem); ok(g_nmlistview.lParam == item.lParam, "Unexpected lParam.\n"); ok(g_nmlistview.uNewState == LVIS_SELECTED, "got new state 0x%08x\n", g_nmlistview.uNewState); ok(g_nmlistview.uOldState == 0, "got old state 0x%08x\n", g_nmlistview.uOldState); ok(g_nmlistview.uChanged == LVIF_STATE, "got changed 0x%08x\n", g_nmlistview.uChanged);
/* LVM_SETITEMSTATE 0 mask */ memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview)); memset(&item, 0, sizeof(item)); item.stateMask = LVIS_SELECTED; item.state = 0; res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item); ok(res, "Failed to set item state.\n");
ok(g_nmlistview.iItem == item.iItem, "Unexpected item %d.\n", g_nmlistview.iItem); ok(g_nmlistview.iSubItem == item.iSubItem, "Unexpected subitem %d.\n", g_nmlistview.iSubItem); ok(g_nmlistview.lParam == item.lParam, "Unexpected lParam.\n"); ok(g_nmlistview.uNewState == 0, "Unexpected new state %#x.\n", g_nmlistview.uNewState); ok(g_nmlistview.uOldState == LVIS_SELECTED, "Unexpected old state %#x.\n", g_nmlistview.uOldState); ok(g_nmlistview.uChanged == LVIF_STATE, "Unexpected change mask %#x.\n", g_nmlistview.uChanged);
/* LVM_SETITEM changes state */ memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview)); memset(&item, 0, sizeof(item)); item.stateMask = LVIS_SELECTED; item.state = LVIS_SELECTED; item.mask = LVIF_STATE; res = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item); ok(res, "Failed to set item.\n");
ok(g_nmlistview.iItem == item.iItem, "Unexpected item %d.\n", g_nmlistview.iItem); ok(g_nmlistview.iSubItem == item.iSubItem, "Unexpected subitem %d.\n", g_nmlistview.iSubItem); ok(g_nmlistview.lParam == item.lParam, "Unexpected lParam.\n"); ok(g_nmlistview.uNewState == LVIS_SELECTED, "Unexpected new state %#x.\n", g_nmlistview.uNewState); ok(g_nmlistview.uOldState == 0, "Unexpected old state %#x.\n", g_nmlistview.uOldState); ok(g_nmlistview.uChanged == LVIF_STATE, "Unexpected change mask %#x.\n", g_nmlistview.uChanged);
/* LVM_SETITEM no state changes */ memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview)); memset(&item, 0, sizeof(item)); item.lParam = 11; item.mask = LVIF_PARAM; res = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item); ok(res, "Failed to set item.\n");
ok(g_nmlistview.iItem == item.iItem, "Unexpected item %d.\n", g_nmlistview.iItem); ok(g_nmlistview.iSubItem == item.iSubItem, "Unexpected subitem %d.\n", g_nmlistview.iSubItem); ok(g_nmlistview.lParam == item.lParam, "Unexpected lParam.\n"); ok(g_nmlistview.uNewState == 0, "Unexpected new state %#x.\n", g_nmlistview.uNewState); ok(g_nmlistview.uOldState == 0, "Unexpected old state %#x.\n", g_nmlistview.uOldState); ok(g_nmlistview.uChanged == LVIF_PARAM, "Unexpected change mask %#x.\n", g_nmlistview.uChanged);
DestroyWindow(hwnd); }}
START_TEST(listview){ ULONG_PTR ctx_cookie; HANDLE hCtx;
init_functions();
init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
hwndparent = create_parent_window(FALSE); flush_sequences(sequences, NUM_MSG_SEQUENCES);
g_is_below_5 = is_below_comctl_5();
test_header_notification(); test_header_notification2(); test_images(); test_checkboxes(); test_items(); test_create(FALSE); test_redraw(); test_customdraw(); test_icon_spacing(); test_color(); test_item_count(); test_item_position(); test_columns(); test_getorigin(); test_multiselect(); test_getitemrect(); test_subitem_rect(); test_sorting(); test_ownerdata(); test_norecompute(); test_nosortheader(); test_setredraw(); test_hittest(); test_getviewrect(); test_getitemposition(); test_editbox(); test_notifyformat(); test_indentation(); test_getitemspacing(); test_getcolumnwidth(); test_approximate_viewrect(); test_finditem(); test_hover(); test_destroynotify(); test_createdragimage(); test_dispinfo(); test_LVM_SETITEMTEXT(); test_LVM_REDRAWITEMS(); test_imagelists(); test_deleteitem(); test_insertitem(); test_header_proc(); test_oneclickactivate(); test_callback_mask(); test_state_image(); test_LVSCW_AUTOSIZE(); test_LVN_ENDLABELEDIT(); test_LVM_GETCOUNTPERPAGE(); test_item_state_change();
if (!load_v6_module(&ctx_cookie, &hCtx)) { DestroyWindow(hwndparent); return; }
init_functions();
/* comctl32 version 6 tests start here */ test_get_set_view(); test_canceleditlabel(); test_mapidindex(); test_scrollnotify(); test_LVS_EX_TRANSPARENTBKGND(); test_LVS_EX_HEADERINALLVIEWS(); test_deleteitem(); test_multiselect(); test_insertitem(); test_header_proc(); test_images(); test_checkboxes(); test_items(); test_create(TRUE); test_color(); test_columns(); test_sorting(); test_ownerdata(); test_norecompute(); test_nosortheader(); test_indentation(); test_finditem(); test_hover(); test_destroynotify(); test_createdragimage(); test_dispinfo(); test_LVM_SETITEMTEXT(); test_LVM_REDRAWITEMS(); test_oneclickactivate(); test_state_image(); test_LVSCW_AUTOSIZE(); test_LVN_ENDLABELEDIT(); test_LVM_GETCOUNTPERPAGE(); test_item_state_change();
unload_v6_module(ctx_cookie, hCtx);
DestroyWindow(hwndparent);}