12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259 |
- // GridCtrl.cpp : implementation file
- //
- // MFC Grid Control v2.23
- //
- // Written by Chris Maunder <cmaunder@mail.com>
- // Copyright (c) 1998-2001. All Rights Reserved.
- //
- // The code contained in this file is based on the original
- // WorldCom Grid control written by Joe Willcoxson,
- // mailto:chinajoe@aol.com
- // http://users.aol.com/chinajoe
- // (These addresses may be out of date) The code has gone through
- // so many modifications that I'm not sure if there is even a single
- // original line of code. In any case Joe's code was a great
- // framework on which to build.
- //
- // This code may be used in compiled form in any way you desire. This
- // file may be redistributed unmodified by any means PROVIDING it is
- // not sold for profit without the authors written consent, and
- // providing that this notice and the authors name and all copyright
- // notices remains intact.
- //
- // An email letting me know how you are using it would be nice as well.
- //
- // This file is provided "as is" with no expressed or implied warranty.
- // The author accepts no liability for any damage/loss of business that
- // this product may cause.
- //
- // Expect bugs!
- //
- // Please use and enjoy, and let me know of any bugs/mods/improvements
- // that you have found/implemented and I will fix/incorporate them into
- // this file.
- //
- // History:
- // --------
- // This control is constantly evolving, sometimes due to new features that I
- // feel are necessary, and sometimes due to existing bugs. Where possible I
- // have credited the changes to those who contributed code corrections or
- // enhancements (names in brackets) or code suggestions (suggested by...)
- //
- // 1.0 - 1.13 20 Feb 1998 - 6 May 1999
- // First release version. Progressed from being a basic
- // grid based on the original WorldCom Grid control
- // written by Joe Willcoxson (mailto:chinajoe@aol.com,
- // http://users.aol.com/chinajoe) to something a little
- // more feature rich. Rewritten so many times I doubt
- // there is a single line of Joe's code left. Many, many,
- // MANY people sent in bug reports and fixes. Thank you
- // all.
- //
- // 2.0 1 Feb 2000
- // Rewritten to make the grid more object oriented, in
- // that the CGridCell class now takes care of cell-specific
- // tasks. This makes the code more robust, but more
- // importantly it allows the simple insertion of other
- // types of cells.
- //
- // 2.01 20 Feb 2000 - Eric Woodruff
- // Added better support for printing grids and
- // also fixed some other minor problems.
- //
- // 2.02 29 Feb 2000 - Brian V. Shifrin, Scot Reed,
- // Fixes to reduce flicker, fix font selection bug,
- // Fixed SetFixed[Row/Col]Count bug
- //
- // 2.03 28 Mar 2000 - Aqiruse (marked with //FNA)
- // Titletips now use cell color
- //
- // 2.10 11 Mar 2000 - Ken Bertelson and Chris Maunder
- // - Additions for virtual CGridCell support of embedded tree
- // & cell buttons implementation
- // - Optional WYSIWYG printing
- // - Awareness of hidden (0 width/height) rows and columns for
- // key movements, cut, copy, paste, and autosizing
- // - CGridCell can make title tips display any text rather than
- // cell text only
- // - Minor vis bug fixes
- // - CGridCtrl now works with CGridCellBase instead of CGridCell
- // This is a taste of things to come.
- //
- // 2.11 19 May 2000 - Chris Maunder
- // - Increasing fixed cells clashed with selected cells (Ivan Ilinov)
- // - AutoSizeRows obvous bug fixed
- // - OnLButtonDown fix (Ken Bertelson)
- // - ExpandToFit bug fixed (scrollbar space) (Igor Proskuriakov)
- // - List mode selection/deselection fixed
- // - Keyboard cell movement improved. You can now see the cells!
- // - m_nBarState MS madness fixed (Phil K)
- //
- // 2.12 26 May 2000 - Martin Richter
- // - If using TRY/CATCH (winCE) instead of try/catch (win32),
- // e->Delete is not called
- // - EnsureVisible "fix" was fixed properly.
- //
- // 2.20 30 Jul 2000 - Chris Maunder
- // - Font storage optimised (suggested by Martin Richter)
- // - AutoSizeColumn works on either column header, data or both
- // - EnsureVisible. The saga continues... (Ken)
- // - Rewrote exception handling
- // - Added TrackFocusCell and FrameFocusCell properties, as well as
- // ExpandLastColumn (suggested by Bruce E. Stemplewski).
- // - InsertColumn now allows you to insert columns at the end of the
- // column range (David Weibel)
- // - Shift-cell-selection more intuitive
- // - API change: Set/GetGridColor now Set/GetGridLineColor
- // - API change: Set/GetBkColor now Set/GetGridBkColor
- // - API change: Set/GetTextColor, Set/GetTextBkColor depricated
- // - API change: Set/GetFixedTextColor, Set/GetFixedBkColor depricated
- // - Stupid DDX_GridControl workaround removed.
- // - Added "virtual mode" via Set/GetVirtualMode
- // - Added SetCallbackFunc to allow callback functions in virtual mode
- // - Added Set/GetAutoSizeStyle
- // - AutoSize() bug fixed
- // - added GVIS_FIXEDROW, GVIS_FIXEDCOL states
- // - added Get/SetFixed[Row|Column]Selection
- // - cell "Get" methods now const'd. Sorry folks...
- // - GetMouseScrollLines now uses win98/W2K friendly code
- // - WS_EX_CLIENTEDGE style now implicit
- //
- // 2.21 29 Aug 2000 - Chris Maunder
- // - re-jigged OLE initialisation and drag/drop registration
- // - Cut and Paste bug fixed (empty cells not being treated correctly)
- // - Added "bExpandFixed" parameter to Expand*ToFit functions (Hans-Peter Werner)
- // - SetRedraw bug fixed
- // - Resizing 0-width last row and column now works
- // - Fixed CreateCell SetFormat bug (Loic Baudry)
- // - Fixed GetFixedTextColor typo (raybie@Exabyte.COM)
- // - Modified EnableScrollBars calls in Expand*ToFit functions (Simon Hughes)
- // - GetCellFromPt now public
- // - GV_CACHEHINT sent more appropriately, and also sent with -1 cellrange
- // at the end of operations (so App can discard data - Martin Richter)
- // - CGridCellBase::operator= checks for NULL font before setting (Martin Richter)
- // - After drag/drop, mouse button was still marked as "down". Fixed.
- //
- // 2.22 1 Jan 2001 - Chris Maunder
- // - SetModified bug in SetItem (Keith Worden)
- // - ifdef around SetItemTextFmt corrected for win32
- // - Save() bug fixed (row 0 saved twice)
- // - GetTopleftNonFixedCell, GetUnobstructedNonFixedCellRange and
- // GetVisibleNonFixedCellRange have optional parameter to force recalc.
- // - added virtual ValidateEdit.
- // - if the return value from the SendMessage operation for
- // GVN_ENDLABELEDIT or GVN_BEGINLABELEDIT is < 0 then the
- // edit, or the attempt to edit (respectively) is rejected.
- // - Added GetEditWnd to CGridCellBase
- // - Fixed the paste bug for cells being edited (Gary Lyben).
- // - GVN_SELCHANGING/GVN_SELCHANGED messages now sent correctly
- // - OnRButtonUp was not handling clicks on fixed cells correctly
- // - SB_ENDSCROLL message now sent on keypress initiated scroll
- // - GetCellTextExtent bug fixed (Elco)
- // - SetSelectedRange inefficiency fixed by huangchaoyi <ahaa007@263.net>
- // - DT_NOCLIP removed from CGridCellBase::Paint
- // - SetRowCount returns correct value on OOM condition (asigal@hotmail.com)
- // - Bug when editing using Japanese characters fixed (Michael Dunn)
- // - Fixed columns and rows printed correctly (fletch - untested)
- // - Added the "ClearCells" function
- //
- // TODO: 1) Implement sparse grids (super easy now)
- // 2) Fix it so that as you drag select, the speed of selection increases
- // with time.
- // 3) Scrolling is still a little dodgy (too much grey area). I know there
- // is a simple fix but it's been a low priority5
- // 4) Get some sleep
- //
- // ISSUES: 1) Crashes in the HPC/Pro emulation - but works fine on a device. ???
- // 2) WindowFromPoint seems to do weird things in W2K. Causing problems for
- // the rigt-click-on-titletip code.
- //
- /////////////////////////////////////////////////////////////////////////////
- #include "stdafx.h"
- #include "MemDC.h"
- #include "GridCtrl.h"
- // OLE stuff for clipboard operations
- #include <afxadv.h> // For CSharedFile
- #include <afxconv.h> // For LPTSTR -> LPSTR macros
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- // Spit out some messages as a sanity check for programmers
- #ifdef GRIDCONTROL_NO_TITLETIPS
- #pragma message(" -- CGridCtrl: No titletips for cells with large data")
- #endif
- #ifdef GRIDCONTROL_NO_DRAGDROP
- #pragma message(" -- CGridCtrl: No OLE drag and drop")
- #endif
- #ifdef GRIDCONTROL_NO_CLIPBOARD
- #pragma message(" -- CGridCtrl: No clipboard support")
- #endif
- #ifdef GRIDCONTROL_NO_PRINTING
- #pragma message(" -- CGridCtrl: No printing support")
- #endif
- IMPLEMENT_DYNCREATE(CGridCtrl, CWnd)
- // Get the number of lines to scroll with each mouse wheel notch
- // Why doesn't windows give us this function???
- UINT GetMouseScrollLines()
- {
- int nScrollLines = 3; // reasonable default
- #ifndef _WIN32_WCE
- // Do things the hard way in win95
- OSVERSIONINFO VersionInfo;
- VersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- if (!GetVersionEx(&VersionInfo) ||
- (VersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && VersionInfo.dwMinorVersion == 0))
- {
- HKEY hKey;
- if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Control Panel\\Desktop"),
- 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
- {
- TCHAR szData[128];
- DWORD dwKeyDataType;
- DWORD dwDataBufSize = sizeof(szData);
- if (RegQueryValueEx(hKey, _T("WheelScrollLines"), NULL, &dwKeyDataType,
- (LPBYTE)&szData, &dwDataBufSize) == ERROR_SUCCESS)
- {
- nScrollLines = _tcstoul(szData, NULL, 10);
- }
- RegCloseKey(hKey);
- }
- }
- // win98 or greater
- else
- SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &nScrollLines, 0);
- #endif
- return nScrollLines;
- }
- /////////////////////////////////////////////////////////////////////////////
- // CGridCtrl
- CGridCtrl::CGridCtrl(int nRows, int nCols, int nFixedRows, int nFixedCols)
- {
- RegisterWindowClass();
- #if !defined(GRIDCONTROL_NO_DRAGDROP) || !defined(GRIDCONTROL_NO_CLIPBOARD)
- _AFX_THREAD_STATE* pState = AfxGetThreadState();
- if (!pState->m_bNeedTerm && !AfxOleInit())
- AfxMessageBox(_T("OLE initialization failed. Make sure that the OLE libraries are the correct version"));
- #endif
- // Store the system colours in case they change. The gridctrl uses
- // these colours, and in OnSysColorChange we can check to see if
- // the gridctrl colours have been changed from the system colours.
- // If they have, then leave them, otherwise change them to reflect
- // the new system colours.
- m_crWindowText = ::GetSysColor(COLOR_WINDOWTEXT);
- m_crWindowColour = ::GetSysColor(COLOR_WINDOW);
- m_cr3DFace = ::GetSysColor(COLOR_3DFACE);
- m_crShadow = ::GetSysColor(COLOR_3DSHADOW);
- m_crGridLineColour = RGB(192, 192, 192);
- m_nRows = 0;
- m_nCols = 0;
- m_nFixedRows = 0;
- m_nFixedCols = 0;
- m_bVirtualMode = FALSE;
- m_pfnCallback = NULL;
- m_nVScrollMax = 0; // Scroll position
- m_nHScrollMax = 0;
- m_nRowsPerWheelNotch = GetMouseScrollLines(); // Get the number of lines
- // per mouse wheel notch to scroll
- m_nBarState = GVL_NONE;
- m_MouseMode = MOUSE_NOTHING;
- m_nGridLines = GVL_BOTH;
- m_bEditable = TRUE;
- m_bListMode = FALSE;
- m_bSingleRowSelection = FALSE;
- m_bSingleColSelection = FALSE;
- m_bLMouseButtonDown = FALSE;
- m_bRMouseButtonDown = FALSE;
- m_bAllowDraw = TRUE; // allow draw updates
- m_bEnableSelection = TRUE;
- m_bFixedColumnSelection = TRUE;
- m_bFixedRowSelection = TRUE;
- m_bAllowRowResize = TRUE;
- m_bAllowColumnResize = TRUE;
- m_bSortOnClick = FALSE; // Sort on header row click
- m_bHandleTabKey = TRUE;
- #ifdef _WIN32_WCE
- m_bDoubleBuffer = FALSE; // Use double buffering to avoid flicker?
- #else
- m_bDoubleBuffer = TRUE; // Use double buffering to avoid flicker?
- #endif
- m_bTitleTips = TRUE; // show cell title tips
- m_bWysiwygPrinting = FALSE; // use size-to-width printing
- m_bHiddenColUnhide = TRUE; // 0-width columns can be expanded via mouse
- m_bHiddenRowUnhide = TRUE; // 0-Height rows can be expanded via mouse
- m_bAllowColHide = TRUE; // Columns can be contracted to 0-width via mouse
- m_bAllowRowHide = TRUE; // Rows can be contracted to 0-height via mouse
- m_bAscending = TRUE; // sorting stuff
- m_nSortColumn = -1;
- m_pfnCompare = NULL;
- m_nAutoSizeColumnStyle = GVS_BOTH; // Autosize grid using header and data info
- m_nTimerID = 0; // For drag-selection
- m_nTimerInterval = 25; // (in milliseconds)
- m_nResizeCaptureRange = 3; // When resizing columns/row, the cursor has to be
- // within +/-3 pixels of the dividing line for
- // resizing to be possible
- m_pImageList = NULL; // Images in the grid
- m_bAllowDragAndDrop = FALSE; // for drag and drop - EFW - off by default
- m_bTrackFocusCell = TRUE; // Track Focus cell?
- m_bFrameFocus = TRUE; // Frame the selected cell?
- m_pRtcDefault = RUNTIME_CLASS(CGridCell);
- SetupDefaultCells();
- SetGridBkColor(m_crShadow);
- // Set up the initial grid size
- SetRowCount(nRows);
- SetColumnCount(nCols);
- SetFixedRowCount(nFixedRows);
- SetFixedColumnCount(nFixedCols);
- SetTitleTipTextClr(CLR_DEFAULT); //FNA
- SetTitleTipBackClr(CLR_DEFAULT);
- // set initial selection range (ie. none)
- m_SelectedCellMap.RemoveAll();
- m_PrevSelectedCellMap.RemoveAll();
- #if !defined(_WIN32_WCE_NO_PRINTING) && !defined(GRIDCONTROL_NO_PRINTING)
- // EFW - Added to support shaded/unshaded printout and
- // user-definable margins.
- m_bShadedPrintOut = TRUE;
- SetPrintMarginInfo(2, 2, 4, 4, 1, 1, 1);
- #endif
- }
- CGridCtrl::~CGridCtrl()
- {
- DeleteAllItems();
- #ifndef GRIDCONTROL_NO_TITLETIPS
- if (m_bTitleTips && ::IsWindow(m_TitleTip.GetSafeHwnd()))
- m_TitleTip.DestroyWindow();
- #endif
- DestroyWindow();
- #if !defined(GRIDCONTROL_NO_DRAGDROP) || !defined(GRIDCONTROL_NO_CLIPBOARD)
- // BUG FIX - EFW
- COleDataSource *pSource = COleDataSource::GetClipboardOwner();
- if (pSource)
- COleDataSource::FlushClipboard();
- #endif
- }
- // Register the window class if it has not already been registered.
- BOOL CGridCtrl::RegisterWindowClass(HINSTANCE hInstance)
- {
- WNDCLASS wndcls;
- //HINSTANCE hInst = AfxGetInstanceHandle();
- //HINSTANCE hInst = AfxGetResourceHandle();
- HINSTANCE hInst = hInstance ? hInstance : AfxGetInstanceHandle();
- if (!(::GetClassInfo(hInst, GRIDCTRL_CLASSNAME, &wndcls)))
- {
- // otherwise we need to register a new class
- wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
- wndcls.lpfnWndProc = ::DefWindowProc;
- wndcls.cbClsExtra = wndcls.cbWndExtra = 0;
- wndcls.hInstance = hInst;
- wndcls.hIcon = NULL;
- #ifndef _WIN32_WCE_NO_CURSOR
- wndcls.hCursor = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
- #else
- wndcls.hCursor = 0;
- #endif
- wndcls.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
- wndcls.lpszMenuName = NULL;
- wndcls.lpszClassName = GRIDCTRL_CLASSNAME;
- if (!AfxRegisterClass(&wndcls))
- {
- AfxThrowResourceException();
- return FALSE;
- }
- }
- return TRUE;
- }
- BOOL CGridCtrl::Initialise()
- {
- // Stop re-entry problems
- static BOOL bInProcedure = FALSE;
- if (bInProcedure)
- return FALSE;
- bInProcedure = TRUE;
- #ifndef GRIDCONTROL_NO_TITLETIPS
- m_TitleTip.SetParentWnd(this);
- #endif
- if (::IsWindow(m_hWnd))
- ModifyStyleEx(0, WS_EX_CLIENTEDGE, 0);
- bInProcedure = FALSE;
- return TRUE;
- }
- // creates the control - use like any other window create control
- BOOL CGridCtrl::Create(const RECT& rect, CWnd* pParentWnd, UINT nID, DWORD dwStyle)
- {
- ASSERT(pParentWnd->GetSafeHwnd());
- if (!CWnd::Create(GRIDCTRL_CLASSNAME, NULL, dwStyle, rect, pParentWnd, nID))
- return FALSE;
- //Initialise();
- // The number of rows and columns will only be non-zero if the constructor
- // was called with non-zero initialising parameters. If this window was created
- // using a dialog template then the number of rows and columns will be 0 (which
- // means that the code below will not be needed - which is lucky 'cause it ain't
- // gonna get called in a dialog-template-type-situation.
- TRY
- {
- m_arRowHeights.SetSize(m_nRows); // initialize row heights
- m_arColWidths.SetSize(m_nCols); // initialize column widths
- }
- CATCH(CMemoryException, e)
- {
- e->ReportError();
- return FALSE;
- }
- END_CATCH
- int i;
- for (i = 0; i < m_nRows; i++)
- m_arRowHeights[i] = m_cellDefault.GetHeight();
- for (i = 0; i < m_nCols; i++)
- m_arColWidths[i] = m_cellDefault.GetWidth();
- ResetScrollBars(); //- called in OnSize anyway
- return TRUE;
- }
- void CGridCtrl::SetupDefaultCells()
- {
- m_cellDefault.SetGrid(this); // Normal editable cell
- m_cellFixedColDef.SetGrid(this); // Cell for fixed columns
- m_cellFixedRowDef.SetGrid(this); // Cell for fixed rows
- m_cellFixedRowColDef.SetGrid(this); // Cell for area overlapped by fixed columns/rows
- m_cellDefault.SetTextClr(m_crWindowText);
- m_cellDefault.SetBackClr(m_crWindowColour);
- m_cellFixedColDef.SetTextClr(m_crWindowText);
- m_cellFixedColDef.SetBackClr(m_cr3DFace);
- m_cellFixedRowDef.SetTextClr(m_crWindowText);
- m_cellFixedRowDef.SetBackClr(m_cr3DFace);
- m_cellFixedRowColDef.SetTextClr(m_crWindowText);
- m_cellFixedRowColDef.SetBackClr(m_cr3DFace);
- }
- void CGridCtrl::PreSubclassWindow()
- {
- CWnd::PreSubclassWindow();
- //HFONT hFont = ::CreateFontIndirect(m_cellDefault.GetFont());
- //OnSetFont((LPARAM)hFont, 0);
- //DeleteObject(hFont);
- Initialise();
- // ResetScrollBars(); - called in OnSize anyway
- }
- // Sends a message to the parent in the form of a WM_NOTIFY message with
- // a NM_GRIDVIEW structure attached
- LRESULT CGridCtrl::SendMessageToParent(int nRow, int nCol, int nMessage) const
- {
- if (!IsWindow(m_hWnd))
- return 0;
- NM_GRIDVIEW nmgv;
- nmgv.iRow = nRow;
- nmgv.iColumn = nCol;
- nmgv.hdr.hwndFrom = m_hWnd;
- nmgv.hdr.idFrom = GetDlgCtrlID();
- nmgv.hdr.code = nMessage;
- CWnd *pOwner = GetOwner();
- if (pOwner && IsWindow(pOwner->m_hWnd))
- return pOwner->SendMessage(WM_NOTIFY, nmgv.hdr.idFrom, (LPARAM)&nmgv);
- else
- return 0;
- }
- // Send a request to the parent to return information on a given cell
- LRESULT CGridCtrl::SendDisplayRequestToParent(GV_DISPINFO* pDisplayInfo) const
- {
- if (!IsWindow(m_hWnd))
- return 0;
- // Fix up the message headers
- pDisplayInfo->hdr.hwndFrom = m_hWnd;
- pDisplayInfo->hdr.idFrom = GetDlgCtrlID();
- pDisplayInfo->hdr.code = GVN_GETDISPINFO;
- // Send the message
- CWnd *pOwner = GetOwner();
- if (pOwner && IsWindow(pOwner->m_hWnd))
- return pOwner->SendMessage(WM_NOTIFY, pDisplayInfo->hdr.idFrom, (LPARAM)pDisplayInfo);
- else
- return 0;
- }
- // Send a hint to the parent about caching information
- LRESULT CGridCtrl::SendCacheHintToParent(const CCellRange& range) const
- {
- if (!IsWindow(m_hWnd))
- return 0;
- GV_CACHEHINT CacheHint;
- // Fix up the message headers
- CacheHint.hdr.hwndFrom = m_hWnd;
- CacheHint.hdr.idFrom = GetDlgCtrlID();
- CacheHint.hdr.code = GVN_ODCACHEHINT;
- CacheHint.range = range;
- // Send the message
- CWnd *pOwner = GetOwner();
- if (pOwner && IsWindow(pOwner->m_hWnd))
- return pOwner->SendMessage(WM_NOTIFY, CacheHint.hdr.idFrom, (LPARAM)&CacheHint);
- else
- return 0;
- }
- BEGIN_MESSAGE_MAP(CGridCtrl, CWnd)
- //EFW - Added ON_WM_RBUTTONUP
- //{{AFX_MSG_MAP(CGridCtrl)
- ON_WM_PAINT()
- ON_WM_HSCROLL()
- ON_WM_VSCROLL()
- ON_WM_SIZE()
- ON_WM_LBUTTONUP()
- ON_WM_LBUTTONDOWN()
- ON_WM_MOUSEMOVE()
- ON_WM_TIMER()
- ON_WM_GETDLGCODE()
- ON_WM_KEYDOWN()
- ON_WM_CHAR()
- ON_WM_LBUTTONDBLCLK()
- ON_WM_ERASEBKGND()
- ON_UPDATE_COMMAND_UI(ID_EDIT_SELECT_ALL, OnUpdateEditSelectAll)
- ON_COMMAND(ID_EDIT_SELECT_ALL, OnEditSelectAll)
- ON_WM_SYSKEYDOWN()
- //}}AFX_MSG_MAP
- #ifndef _WIN32_WCE_NO_CURSOR
- ON_WM_SETCURSOR()
- #endif
- #ifndef _WIN32_WCE
- ON_WM_RBUTTONUP()
- ON_WM_SYSCOLORCHANGE()
- ON_WM_CAPTURECHANGED()
- #endif
- #ifndef GRIDCONTROL_NO_CLIPBOARD
- ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
- ON_UPDATE_COMMAND_UI(ID_EDIT_COPY, OnUpdateEditCopy)
- ON_COMMAND(ID_EDIT_CUT, OnEditCut)
- ON_UPDATE_COMMAND_UI(ID_EDIT_CUT, OnUpdateEditCut)
- ON_COMMAND(ID_EDIT_PASTE, OnEditPaste)
- ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, OnUpdateEditPaste)
- #endif
- #if (_WIN32_WCE >= 210)
- ON_WM_SETTINGCHANGE()
- #endif
- #if !defined(_WIN32_WCE) && (_MFC_VER >= 0x0421)
- ON_WM_MOUSEWHEEL()
- #endif
- ON_MESSAGE(WM_SETFONT, OnSetFont)
- ON_MESSAGE(WM_GETFONT, OnGetFont)
- ON_MESSAGE(WM_IME_CHAR, OnImeChar)
- ON_NOTIFY(GVN_ENDLABELEDIT, IDC_INPLACE_CONTROL, OnEndInPlaceEdit)
- END_MESSAGE_MAP()
- /////////////////////////////////////////////////////////////////////////////
- // CGridCtrl message handlers
- void CGridCtrl::OnPaint()
- {
- CPaintDC dc(this); // device context for painting
- if (m_bDoubleBuffer) // Use a memory DC to remove flicker
- {
- CMemDC MemDC(&dc);
- OnDraw(&MemDC);
- }
- else // Draw raw - this helps in debugging vis problems.
- OnDraw(&dc);
- }
- BOOL CGridCtrl::OnEraseBkgnd(CDC* /*pDC*/)
- {
- return TRUE; // Don't erase the background.
- }
- // Custom background erasure. This gets called from within the OnDraw function,
- // since we will (most likely) be using a memory DC to stop flicker. If we just
- // erase the background normally through OnEraseBkgnd, and didn't fill the memDC's
- // selected bitmap with colour, then all sorts of vis problems would occur
- void CGridCtrl::EraseBkgnd(CDC* pDC)
- {
- CRect VisRect, ClipRect, rect;
- CBrush FixedRowColBack(GetDefaultCell(TRUE, TRUE)->GetBackClr()),
- FixedRowBack(GetDefaultCell(TRUE, FALSE)->GetBackClr()),
- FixedColBack(GetDefaultCell(FALSE, TRUE)->GetBackClr()),
- TextBack(GetDefaultCell(FALSE, FALSE)->GetBackClr());
- CBrush Back(GetGridBkColor());
- //CBrush Back(GetTextBkColor());
- if (pDC->GetClipBox(ClipRect) == ERROR)
- return;
- GetVisibleNonFixedCellRange(VisRect);
- int nFixedColumnWidth = GetFixedColumnWidth();
- int nFixedRowHeight = GetFixedRowHeight();
- // Draw Fixed row/column background
- if (ClipRect.left < nFixedColumnWidth && ClipRect.top < nFixedRowHeight)
- pDC->FillRect(CRect(ClipRect.left, ClipRect.top,
- nFixedColumnWidth, nFixedRowHeight),
- &FixedRowColBack);
- // Draw Fixed columns background
- if (ClipRect.left < nFixedColumnWidth && ClipRect.top < VisRect.bottom)
- pDC->FillRect(CRect(ClipRect.left, ClipRect.top,
- nFixedColumnWidth, VisRect.bottom),
- &FixedColBack);
- // Draw Fixed rows background
- if (ClipRect.top < nFixedRowHeight &&
- ClipRect.right > nFixedColumnWidth && ClipRect.left < VisRect.right)
- pDC->FillRect(CRect(nFixedColumnWidth - 1, ClipRect.top,
- VisRect.right, nFixedRowHeight),
- &FixedRowBack);
- // Draw non-fixed cell background
- if (rect.IntersectRect(VisRect, ClipRect))
- {
- CRect CellRect(max(nFixedColumnWidth, rect.left),
- max(nFixedRowHeight, rect.top),
- rect.right, rect.bottom);
- pDC->FillRect(CellRect, &TextBack);
- }
- // Draw right hand side of window outside grid
- if (VisRect.right < ClipRect.right)
- pDC->FillRect(CRect(VisRect.right, ClipRect.top,
- ClipRect.right, ClipRect.bottom),
- &Back);
- // Draw bottom of window below grid
- if (VisRect.bottom < ClipRect.bottom && ClipRect.left < VisRect.right)
- pDC->FillRect(CRect(ClipRect.left, VisRect.bottom,
- VisRect.right, ClipRect.bottom),
- &Back);
- }
- void CGridCtrl::OnSize(UINT nType, int cx, int cy)
- {
- static BOOL bAlreadyInsideThisProcedure = FALSE;
- if (bAlreadyInsideThisProcedure)
- return;
- if (!::IsWindow(m_hWnd))
- return;
- // This hurts - but I need a place for initialisation for the drop target,
- // and the window must be created. "Create" is a good place - if one is
- // creating the window dynamically. If one is using a dialog template then
- // this is no good. Oh well...
- # ifndef GRIDCONTROL_NO_DRAGDROP
- m_DropTarget.Register(this);
- # endif
- // Start re-entry blocking
- bAlreadyInsideThisProcedure = TRUE;
- EndEditing(); // destroy any InPlaceEdit's
- CWnd::OnSize(nType, cx, cy);
- ResetScrollBars();
- // End re-entry blocking
- bAlreadyInsideThisProcedure = FALSE;
- }
- UINT CGridCtrl::OnGetDlgCode()
- {
- UINT nCode = DLGC_WANTARROWS | DLGC_WANTCHARS; // DLGC_WANTALLKEYS; //
- if (m_bHandleTabKey && !IsCTRLpressed())
- nCode |= DLGC_WANTTAB;
- return nCode;
- }
- #ifndef _WIN32_WCE
- // If system colours change, then redo colours
- void CGridCtrl::OnSysColorChange()
- {
- CWnd::OnSysColorChange();
- if (GetDefaultCell(FALSE, FALSE)->GetTextClr() == m_crWindowText) // Still using system colours
- GetDefaultCell(FALSE, FALSE)->SetTextClr(::GetSysColor(COLOR_WINDOWTEXT)); // set to new system colour
- if (GetDefaultCell(FALSE, FALSE)->GetBackClr() == m_crWindowColour)
- GetDefaultCell(FALSE, FALSE)->SetBackClr(::GetSysColor(COLOR_WINDOW));
- if (GetDefaultCell(TRUE, FALSE)->GetTextClr() == m_crWindowText) // Still using system colours
- GetDefaultCell(TRUE, FALSE)->SetTextClr(::GetSysColor(COLOR_WINDOWTEXT)); // set to new system colour
- if (GetDefaultCell(TRUE, FALSE)->GetBackClr() == m_crWindowColour)
- GetDefaultCell(TRUE, FALSE)->SetBackClr(::GetSysColor(COLOR_WINDOW));
- if (GetDefaultCell(FALSE, TRUE)->GetTextClr() == m_crWindowText) // Still using system colours
- GetDefaultCell(FALSE, TRUE)->SetTextClr(::GetSysColor(COLOR_WINDOWTEXT)); // set to new system colour
- if (GetDefaultCell(FALSE, TRUE)->GetBackClr() == m_crWindowColour)
- GetDefaultCell(FALSE, TRUE)->SetBackClr(::GetSysColor(COLOR_WINDOW));
- if (GetDefaultCell(TRUE, TRUE)->GetTextClr() == m_crWindowText) // Still using system colours
- GetDefaultCell(TRUE, TRUE)->SetTextClr(::GetSysColor(COLOR_WINDOWTEXT)); // set to new system colour
- if (GetDefaultCell(TRUE, TRUE)->GetBackClr() == m_crWindowColour)
- GetDefaultCell(TRUE, TRUE)->SetBackClr(::GetSysColor(COLOR_WINDOW));
- if (GetGridBkColor() == m_crShadow)
- SetGridBkColor(::GetSysColor(COLOR_3DSHADOW));
- m_crWindowText = ::GetSysColor(COLOR_WINDOWTEXT);
- m_crWindowColour = ::GetSysColor(COLOR_WINDOW);
- m_cr3DFace = ::GetSysColor(COLOR_3DFACE);
- m_crShadow = ::GetSysColor(COLOR_3DSHADOW);
- }
- #endif
- #ifndef _WIN32_WCE_NO_CURSOR
- // If we are drag-selecting cells, or drag and dropping, stop now
- void CGridCtrl::OnCaptureChanged(CWnd *pWnd)
- {
- if (pWnd->GetSafeHwnd() == GetSafeHwnd())
- return;
- // kill timer if active
- if (m_nTimerID != 0)
- {
- KillTimer(m_nTimerID);
- m_nTimerID = 0;
- }
- #ifndef GRIDCONTROL_NO_DRAGDROP
- // Kill drag and drop if active
- if (m_MouseMode == MOUSE_DRAGGING)
- m_MouseMode = MOUSE_NOTHING;
- #endif
- }
- #endif
- #if (_MFC_VER >= 0x0421) || (_WIN32_WCE >= 210)
- // If system settings change, then redo colours
- void CGridCtrl::OnSettingChange(UINT uFlags, LPCTSTR lpszSection)
- {
- CWnd::OnSettingChange(uFlags, lpszSection);
- if (GetDefaultCell(FALSE, FALSE)->GetTextClr() == m_crWindowText) // Still using system colours
- GetDefaultCell(FALSE, FALSE)->SetTextClr(::GetSysColor(COLOR_WINDOWTEXT)); // set to new system colour
- if (GetDefaultCell(FALSE, FALSE)->GetBackClr() == m_crWindowColour)
- GetDefaultCell(FALSE, FALSE)->SetBackClr(::GetSysColor(COLOR_WINDOW));
- if (GetDefaultCell(TRUE, FALSE)->GetTextClr() == m_crWindowText) // Still using system colours
- GetDefaultCell(TRUE, FALSE)->SetTextClr(::GetSysColor(COLOR_WINDOWTEXT)); // set to new system colour
- if (GetDefaultCell(TRUE, FALSE)->GetBackClr() == m_crWindowColour)
- GetDefaultCell(TRUE, FALSE)->SetBackClr(::GetSysColor(COLOR_WINDOW));
- if (GetDefaultCell(FALSE, TRUE)->GetTextClr() == m_crWindowText) // Still using system colours
- GetDefaultCell(FALSE, TRUE)->SetTextClr(::GetSysColor(COLOR_WINDOWTEXT)); // set to new system colour
- if (GetDefaultCell(FALSE, TRUE)->GetBackClr() == m_crWindowColour)
- GetDefaultCell(FALSE, TRUE)->SetBackClr(::GetSysColor(COLOR_WINDOW));
- if (GetDefaultCell(TRUE, TRUE)->GetTextClr() == m_crWindowText) // Still using system colours
- GetDefaultCell(TRUE, TRUE)->SetTextClr(::GetSysColor(COLOR_WINDOWTEXT)); // set to new system colour
- if (GetDefaultCell(TRUE, TRUE)->GetBackClr() == m_crWindowColour)
- GetDefaultCell(TRUE, TRUE)->SetBackClr(::GetSysColor(COLOR_WINDOW));
- if (GetGridBkColor() == m_crShadow)
- SetGridBkColor(::GetSysColor(COLOR_3DSHADOW));
- m_crWindowText = ::GetSysColor(COLOR_WINDOWTEXT);
- m_crWindowColour = ::GetSysColor(COLOR_WINDOW);
- m_cr3DFace = ::GetSysColor(COLOR_3DFACE);
- m_crShadow = ::GetSysColor(COLOR_3DSHADOW);
- m_nRowsPerWheelNotch = GetMouseScrollLines(); // Get the number of lines
- }
- #endif
- // For drag-selection. Scrolls hidden cells into view
- // TODO: decrease timer interval over time to speed up selection over time
- void CGridCtrl::OnTimer(UINT nIDEvent)
- {
- ASSERT(nIDEvent == WM_LBUTTONDOWN);
- if (nIDEvent != WM_LBUTTONDOWN)
- return;
- CPoint pt, origPt;
- #ifdef _WIN32_WCE
- if (m_MouseMode == MOUSE_NOTHING)
- return;
- origPt = GetMessagePos();
- #else
- if (!GetCursorPos(&origPt))
- return;
- #endif
- ScreenToClient(&origPt);
- CRect rect;
- GetClientRect(rect);
- int nFixedRowHeight = GetFixedRowHeight();
- int nFixedColWidth = GetFixedColumnWidth();
- pt = origPt;
- if (pt.y > rect.bottom)
- {
- //SendMessage(WM_VSCROLL, SB_LINEDOWN, 0);
- SendMessage(WM_KEYDOWN, VK_DOWN, 0);
- if (pt.x < rect.left)
- pt.x = rect.left;
- if (pt.x > rect.right)
- pt.x = rect.right;
- pt.y = rect.bottom;
- OnSelecting(GetCellFromPt(pt));
- }
- else if (pt.y < nFixedRowHeight)
- {
- //SendMessage(WM_VSCROLL, SB_LINEUP, 0);
- SendMessage(WM_KEYDOWN, VK_UP, 0);
- if (pt.x < rect.left)
- pt.x = rect.left;
- if (pt.x > rect.right)
- pt.x = rect.right;
- pt.y = nFixedRowHeight + 1;
- OnSelecting(GetCellFromPt(pt));
- }
- pt = origPt;
- if (pt.x > rect.right)
- {
- // SendMessage(WM_HSCROLL, SB_LINERIGHT, 0);
- SendMessage(WM_KEYDOWN, VK_RIGHT, 0);
- if (pt.y < rect.top)
- pt.y = rect.top;
- if (pt.y > rect.bottom)
- pt.y = rect.bottom;
- pt.x = rect.right;
- OnSelecting(GetCellFromPt(pt));
- }
- else if (pt.x < nFixedColWidth)
- {
- //SendMessage(WM_HSCROLL, SB_LINELEFT, 0);
- SendMessage(WM_KEYDOWN, VK_LEFT, 0);
- if (pt.y < rect.top)
- pt.y = rect.top;
- if (pt.y > rect.bottom)
- pt.y = rect.bottom;
- pt.x = nFixedColWidth + 1;
- OnSelecting(GetCellFromPt(pt));
- }
- }
- // move about with keyboard
- void CGridCtrl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
- {
- if (!IsValid(m_idCurrentCell))
- {
- CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
- return;
- }
- CCellID next = m_idCurrentCell;
- BOOL bChangeLine = FALSE;
- BOOL bHorzScrollAction = FALSE;
- BOOL bVertScrollAction = FALSE;
- if (IsCTRLpressed())
- {
- switch (nChar)
- {
- case 'A':
- OnEditSelectAll();
- break;
- #ifndef GRIDCONTROL_NO_CLIPBOARD
- case 'X':
- OnEditCut();
- break;
- case VK_INSERT:
- case 'C':
- OnEditCopy();
- break;
- case 'V':
- OnEditPaste();
- break;
- #endif
- }
- }
- #ifndef GRIDCONTROL_NO_CLIPBOARD
- if (IsSHIFTpressed() && (nChar == VK_INSERT))
- OnEditPaste();
- #endif
- BOOL bFoundVisible;
- int iOrig;
- if (nChar == VK_DELETE)
- {
- ValidateAndModifyCellContents(m_idCurrentCell.row, m_idCurrentCell.col, _T(""));
- }
- else if (nChar == VK_DOWN)
- {
- // don't let user go to a hidden row
- bFoundVisible = FALSE;
- iOrig = next.row;
- next.row++;
- while (next.row < GetRowCount())
- {
- if (GetRowHeight(next.row) > 0)
- {
- bFoundVisible = TRUE;
- break;
- }
- next.row++;
- }
- if (!bFoundVisible)
- next.row = iOrig;
- }
- else if (nChar == VK_UP)
- {
- // don't let user go to a hidden row
- bFoundVisible = FALSE;
- iOrig = next.row;
- next.row--;
- while (next.row >= m_nFixedRows)
- {
- if (GetRowHeight(next.row) > 0)
- {
- bFoundVisible = TRUE;
- break;
- }
- next.row--;
- }
- if (!bFoundVisible)
- next.row = iOrig;
- }
- else if (nChar == VK_RIGHT || (nChar == VK_TAB && !IsSHIFTpressed()))
- {
- // don't let user go to a hidden column
- bFoundVisible = FALSE;
- iOrig = next.col;
- next.col++;
- if (nChar == VK_TAB)
- {
- if (next.col == (GetColumnCount()) && next.row < (GetRowCount() - 1))
- {
- next.row++;
- next.col = m_nFixedCols;
- bChangeLine = TRUE;
- }
- else
- CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
- }
- while (next.col < GetColumnCount())
- {
- if (GetColumnWidth(next.col) > 0)
- {
- bFoundVisible = TRUE;
- break;
- }
- next.col++;
- }
- if (!bFoundVisible)
- next.col = iOrig;
- }
- else if (nChar == VK_LEFT || (nChar == VK_TAB && IsSHIFTpressed()))
- {
- // don't let user go to a hidden column
- bFoundVisible = FALSE;
- iOrig = next.col;
- next.col--;
- if (nChar == VK_TAB)
- {
- if (next.col == (GetFixedColumnCount() - 1) && next.row > GetFixedRowCount())
- {
- next.row--;
- next.col = GetColumnCount() - 1;
- bChangeLine = TRUE;
- }
- else
- CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
- }
- while (next.col >= m_nFixedCols)
- {
- if (GetColumnWidth(next.col) > 0)
- {
- bFoundVisible = TRUE;
- break;
- }
- next.col--;
- }
- if (!bFoundVisible)
- next.col = iOrig;
- }
- else if (nChar == VK_NEXT)
- {
- CCellID idOldTopLeft = GetTopleftNonFixedCell();
- SendMessage(WM_VSCROLL, SB_PAGEDOWN, 0);
- bVertScrollAction = TRUE;
- CCellID idNewTopLeft = GetTopleftNonFixedCell();
- int increment = idNewTopLeft.row - idOldTopLeft.row;
- if (increment)
- {
- next.row += increment;
- if (next.row > (GetRowCount() - 1))
- next.row = GetRowCount() - 1;
- }
- else
- next.row = GetRowCount() - 1;
- }
- else if (nChar == VK_PRIOR)
- {
- CCellID idOldTopLeft = GetTopleftNonFixedCell();
- SendMessage(WM_VSCROLL, SB_PAGEUP, 0);
- bVertScrollAction = TRUE;
- CCellID idNewTopLeft = GetTopleftNonFixedCell();
- int increment = idNewTopLeft.row - idOldTopLeft.row;
- if (increment)
- {
- next.row += increment;
- if (next.row < m_nFixedRows)
- next.row = m_nFixedRows;
- }
- else
- next.row = m_nFixedRows;
- }
- else if (nChar == VK_HOME)
- {
- // Home and Ctrl-Home work more like Excel
- // and don't let user go to a hidden cell
- if (IsCTRLpressed())
- {
- SendMessage(WM_VSCROLL, SB_TOP, 0);
- SendMessage(WM_HSCROLL, SB_LEFT, 0);
- bVertScrollAction = TRUE;
- bHorzScrollAction = TRUE;
- next.row = m_nFixedRows;
- next.col = m_nFixedCols;
- }
- else
- {
- SendMessage(WM_HSCROLL, SB_LEFT, 0);
- bHorzScrollAction = TRUE;
- next.col = m_nFixedCols;
- }
- // adjust column to avoid hidden columns and rows
- while (next.col < GetColumnCount() - 1)
- {
- if (GetColumnWidth(next.col) > 0)
- break;
- next.col++;
- }
- while (next.row < GetRowCount() - 1)
- {
- if (GetRowHeight(next.row) > 0)
- break;
- next.row++;
- }
- }
- else if (nChar == VK_END)
- {
- // End and Ctrl-End work more like Excel
- // and don't let user go to a hidden cell
- if (IsCTRLpressed())
- {
- SendMessage(WM_VSCROLL, SB_BOTTOM, 0);
- SendMessage(WM_HSCROLL, SB_RIGHT, 0);
- bHorzScrollAction = TRUE;
- bVertScrollAction = TRUE;
- next.row = GetRowCount() - 1;
- next.col = GetColumnCount() - 1;
- }
- else
- {
- SendMessage(WM_HSCROLL, SB_RIGHT, 0);
- bHorzScrollAction = TRUE;
- next.col = GetColumnCount() - 1;
- }
- // adjust column to avoid hidden columns and rows
- while (next.col > m_nFixedCols + 1)
- {
- if (GetColumnWidth(next.col) > 0)
- break;
- next.col--;
- }
- while (next.row > m_nFixedRows + 1)
- {
- if (GetRowHeight(next.row) > 0)
- break;
- next.row--;
- }
- }
- else if (nChar == VK_F2)
- {
- OnEditCell(m_idCurrentCell.row, m_idCurrentCell.col, CPoint(-1, -1), VK_LBUTTON);
- }
- else
- {
- CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
- return;
- }
- if (next != m_idCurrentCell)
- {
- // While moving with the Cursorkeys the current ROW/CELL will get selected
- // OR Selection will get expanded when SHIFT is pressed
- // Cut n paste from OnLButtonDown - Franco Bez
- // Added check for NULL mouse mode - Chris Maunder.
- if (m_MouseMode == MOUSE_NOTHING)
- {
- m_PrevSelectedCellMap.RemoveAll();
- m_MouseMode = m_bListMode ? MOUSE_SELECT_ROW : MOUSE_SELECT_CELLS;
- if (!IsSHIFTpressed() || nChar == VK_TAB)
- m_SelectionStartCell = next;
- OnSelecting(next);
- m_MouseMode = MOUSE_NOTHING;
- }
- SetFocusCell(next);
- if (!IsCellVisible(next))
- {
- switch (nChar)
- {
- case VK_RIGHT:
- SendMessage(WM_HSCROLL, SB_LINERIGHT, 0);
- bHorzScrollAction = TRUE;
- break;
- case VK_LEFT:
- SendMessage(WM_HSCROLL, SB_LINELEFT, 0);
- bHorzScrollAction = TRUE;
- break;
- case VK_DOWN:
- SendMessage(WM_VSCROLL, SB_LINEDOWN, 0);
- bVertScrollAction = TRUE;
- break;
- case VK_UP:
- SendMessage(WM_VSCROLL, SB_LINEUP, 0);
- bVertScrollAction = TRUE;
- break;
- case VK_TAB:
- if (IsSHIFTpressed())
- {
- if (bChangeLine)
- {
- SendMessage(WM_VSCROLL, SB_LINEUP, 0);
- bVertScrollAction = TRUE;
- SetScrollPos32(SB_HORZ, m_nHScrollMax);
- break;
- }
- else
- {
- SendMessage(WM_HSCROLL, SB_LINELEFT, 0);
- bHorzScrollAction = TRUE;
- }
- }
- else
- {
- if (bChangeLine)
- {
- SendMessage(WM_VSCROLL, SB_LINEDOWN, 0);
- bVertScrollAction = TRUE;
- SetScrollPos32(SB_HORZ, 0);
- break;
- }
- else
- {
- SendMessage(WM_HSCROLL, SB_LINERIGHT, 0);
- bHorzScrollAction = TRUE;
- }
- }
- break;
- }
- EnsureVisible(next); // Make sure cell is visible
- Invalidate();
- }
- EnsureVisible(next); // Make sure cell is visible
- if (bHorzScrollAction)
- SendMessage(WM_HSCROLL, SB_ENDSCROLL, 0);
- if (bVertScrollAction)
- SendMessage(WM_VSCROLL, SB_ENDSCROLL, 0);
- }
- }
- void CGridCtrl::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
- {
- CWnd::OnKeyUp(nChar, nRepCnt, nFlags);
- }
- void CGridCtrl::OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
- {
- #ifdef GRIDCONTROL_USE_TITLETIPS
- m_TitleTip.Hide(); // hide any titletips
- #endif
- CWnd::OnSysKeyDown(nChar, nRepCnt, nFlags);
- }
- // Instant editing of cells when keys are pressed
- void CGridCtrl::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
- {
- // EFW - BUG FIX
- if (!IsCTRLpressed() && m_MouseMode == MOUSE_NOTHING && nChar != VK_ESCAPE)
- {
- if (!m_bHandleTabKey || (m_bHandleTabKey && nChar != VK_TAB))
- OnEditCell(m_idCurrentCell.row, m_idCurrentCell.col, CPoint(-1, -1), nChar);
- }
- CWnd::OnChar(nChar, nRepCnt, nFlags);
- }
- // Added by KiteFly
- LRESULT CGridCtrl::OnImeChar(WPARAM wCharCode, LPARAM)
- {
- // EFW - BUG FIX
- if (!IsCTRLpressed() && m_MouseMode == MOUSE_NOTHING && wCharCode != VK_ESCAPE)
- OnEditCell(m_idCurrentCell.row, m_idCurrentCell.col, CPoint(-1, -1), wCharCode);
- return 0;
- }
- // Callback from any CInPlaceEdits that ended. This just calls OnEndEditCell,
- // refreshes the edited cell and moves onto next cell if the return character
- // from the edit says we should.
- void CGridCtrl::OnEndInPlaceEdit(NMHDR* pNMHDR, LRESULT* pResult)
- {
- GV_DISPINFO *pgvDispInfo = (GV_DISPINFO *)pNMHDR;
- GV_ITEM *pgvItem = &pgvDispInfo->item;
- // In case OnEndInPlaceEdit called as window is being destroyed
- if (!IsWindow(GetSafeHwnd()))
- return;
- OnEndEditCell(pgvItem->row, pgvItem->col, pgvItem->strText);
- //InvalidateCellRect(CCellID(pgvItem->row, pgvItem->col));
- switch (pgvItem->lParam)
- {
- case VK_TAB:
- case VK_DOWN:
- case VK_UP:
- case VK_RIGHT:
- case VK_LEFT:
- case VK_NEXT:
- case VK_PRIOR:
- case VK_HOME:
- case VK_END:
- OnKeyDown(pgvItem->lParam, 0, 0);
- OnEditCell(m_idCurrentCell.row, m_idCurrentCell.col, CPoint(-1, -1), pgvItem->lParam);
- }
- *pResult = 0;
- }
- // Handle horz scrollbar notifications
- void CGridCtrl::OnHScroll(UINT nSBCode, UINT /*nPos*/, CScrollBar* /*pScrollBar*/)
- {
- EndEditing();
- #ifndef GRIDCONTROL_NO_TITLETIPS
- m_TitleTip.Hide(); // hide any titletips
- #endif
- int scrollPos = GetScrollPos32(SB_HORZ);
- CCellID idTopLeft = GetTopleftNonFixedCell();
- CRect rect;
- GetClientRect(rect);
- switch (nSBCode)
- {
- case SB_LINERIGHT:
- if (scrollPos < m_nHScrollMax)
- {
- // may have contiguous hidden columns. Blow by them
- while (idTopLeft.col < (GetColumnCount() - 1)
- && GetColumnWidth(idTopLeft.col) < 1)
- {
- idTopLeft.col++;
- }
- int xScroll = GetColumnWidth(idTopLeft.col);
- SetScrollPos32(SB_HORZ, scrollPos + xScroll);
- if (GetScrollPos32(SB_HORZ) == scrollPos)
- break; // didn't work
- rect.left = GetFixedColumnWidth();
- //rect.left = GetFixedColumnWidth() + xScroll;
- //ScrollWindow(-xScroll, 0, rect);
- //rect.left = rect.right - xScroll;
- InvalidateRect(rect);
- }
- break;
- case SB_LINELEFT:
- if (scrollPos > 0 && idTopLeft.col > GetFixedColumnCount())
- {
- int iColToUse = idTopLeft.col - 1;
- // may have contiguous hidden columns. Blow by them
- while (iColToUse > GetFixedColumnCount()
- && GetColumnWidth(iColToUse) < 1)
- {
- iColToUse--;
- }
- int xScroll = GetColumnWidth(iColToUse);
- SetScrollPos32(SB_HORZ, max(0, scrollPos - xScroll));
- rect.left = GetFixedColumnWidth();
- //ScrollWindow(xScroll, 0, rect);
- //rect.right = rect.left + xScroll;
- InvalidateRect(rect);
- }
- break;
- case SB_PAGERIGHT:
- if (scrollPos < m_nHScrollMax)
- {
- rect.left = GetFixedColumnWidth();
- int offset = rect.Width();
- int pos = min(m_nHScrollMax, scrollPos + offset);
- SetScrollPos32(SB_HORZ, pos);
- rect.left = GetFixedColumnWidth();
- InvalidateRect(rect);
- }
- break;
- case SB_PAGELEFT:
- if (scrollPos > 0)
- {
- rect.left = GetFixedColumnWidth();
- int offset = -rect.Width();
- int pos = max(0, scrollPos + offset);
- SetScrollPos32(SB_HORZ, pos);
- rect.left = GetFixedColumnWidth();
- InvalidateRect(rect);
- }
- break;
- case SB_THUMBPOSITION:
- case SB_THUMBTRACK:
- {
- SetScrollPos32(SB_HORZ, GetScrollPos32(SB_HORZ, TRUE));
- m_idTopLeftCell.row = -1;
- CCellID idNewTopLeft = GetTopleftNonFixedCell();
- if (idNewTopLeft != idTopLeft)
- {
- rect.left = GetFixedColumnWidth();
- InvalidateRect(rect);
- }
- }
- break;
- case SB_LEFT:
- if (scrollPos > 0)
- {
- SetScrollPos32(SB_HORZ, 0);
- Invalidate();
- }
- break;
- case SB_RIGHT:
- if (scrollPos < m_nHScrollMax)
- {
- SetScrollPos32(SB_HORZ, m_nHScrollMax);
- Invalidate();
- }
- break;
- default:
- break;
- }
- }
- // Handle vert scrollbar notifications
- void CGridCtrl::OnVScroll(UINT nSBCode, UINT /*nPos*/, CScrollBar* /*pScrollBar*/)
- {
- EndEditing();
- #ifndef GRIDCONTROL_NO_TITLETIPS
- m_TitleTip.Hide(); // hide any titletips
- #endif
- // Get the scroll position ourselves to ensure we get a 32 bit value
- int scrollPos = GetScrollPos32(SB_VERT);
- CCellID idTopLeft = GetTopleftNonFixedCell();
- CRect rect;
- GetClientRect(rect);
- switch (nSBCode)
- {
- case SB_LINEDOWN:
- if (scrollPos < m_nVScrollMax)
- {
- // may have contiguous hidden rows. Blow by them
- while (idTopLeft.row < (GetRowCount() - 1)
- && GetRowHeight(idTopLeft.row) < 1)
- {
- idTopLeft.row++;
- }
- int yScroll = GetRowHeight(idTopLeft.row);
- SetScrollPos32(SB_VERT, scrollPos + yScroll);
- if (GetScrollPos32(SB_VERT) == scrollPos)
- break; // didn't work
- rect.top = GetFixedRowHeight();
- //rect.top = GetFixedRowHeight() + yScroll;
- //ScrollWindow(0, -yScroll, rect);
- //rect.top = rect.bottom - yScroll;
- InvalidateRect(rect);
- }
- break;
- case SB_LINEUP:
- if (scrollPos > 0 && idTopLeft.row > GetFixedRowCount())
- {
- int iRowToUse = idTopLeft.row - 1;
- // may have contiguous hidden rows. Blow by them
- while (iRowToUse > GetFixedRowCount()
- && GetRowHeight(iRowToUse) < 1)
- {
- iRowToUse--;
- }
- int yScroll = GetRowHeight(iRowToUse);
- SetScrollPos32(SB_VERT, max(0, scrollPos - yScroll));
- rect.top = GetFixedRowHeight();
- //ScrollWindow(0, yScroll, rect);
- //rect.bottom = rect.top + yScroll;
- InvalidateRect(rect);
- }
- break;
- case SB_PAGEDOWN:
- if (scrollPos < m_nVScrollMax)
- {
- rect.top = GetFixedRowHeight();
- scrollPos = min(m_nVScrollMax, scrollPos + rect.Height());
- SetScrollPos32(SB_VERT, scrollPos);
- rect.top = GetFixedRowHeight();
- InvalidateRect(rect);
- }
- break;
- case SB_PAGEUP:
- if (scrollPos > 0)
- {
- rect.top = GetFixedRowHeight();
- int offset = -rect.Height();
- int pos = max(0, scrollPos + offset);
- SetScrollPos32(SB_VERT, pos);
- rect.top = GetFixedRowHeight();
- InvalidateRect(rect);
- }
- break;
- case SB_THUMBPOSITION:
- case SB_THUMBTRACK:
- {
- SetScrollPos32(SB_VERT, GetScrollPos32(SB_VERT, TRUE));
- m_idTopLeftCell.row = -1;
- CCellID idNewTopLeft = GetTopleftNonFixedCell();
- if (idNewTopLeft != idTopLeft)
- {
- rect.top = GetFixedRowHeight();
- InvalidateRect(rect);
- }
- }
- break;
- case SB_TOP:
- if (scrollPos > 0)
- {
- SetScrollPos32(SB_VERT, 0);
- Invalidate();
- }
- break;
- case SB_BOTTOM:
- if (scrollPos < m_nVScrollMax)
- {
- SetScrollPos32(SB_VERT, m_nVScrollMax);
- Invalidate();
- }
- default:
- break;
- }
- }
- /////////////////////////////////////////////////////////////////////////////
- // CGridCtrl implementation functions
- void CGridCtrl::OnDraw(CDC* pDC)
- {
- if (!m_bAllowDraw)
- return;
- CRect clipRect;
- if (pDC->GetClipBox(&clipRect) == ERROR)
- return;
- EraseBkgnd(pDC); // OnEraseBkgnd does nothing, so erase bkgnd here.
- // This necessary since we may be using a Memory DC.
- CRect rect;
- int row, col;
- CGridCellBase* pCell;
- int nFixedRowHeight = GetFixedRowHeight();
- int nFixedColWidth = GetFixedColumnWidth();
- CCellID idTopLeft = GetTopleftNonFixedCell();
- int minVisibleRow = idTopLeft.row,
- minVisibleCol = idTopLeft.col;
- CRect VisRect;
- CCellRange VisCellRange = GetVisibleNonFixedCellRange(VisRect);
- int maxVisibleRow = VisCellRange.GetMaxRow(),
- maxVisibleCol = VisCellRange.GetMaxCol();
- if (GetVirtualMode())
- SendCacheHintToParent(VisCellRange);
- // draw top-left cells 0..m_nFixedRows-1, 0..m_nFixedCols-1
- rect.bottom = -1;
- for (row = 0; row < m_nFixedRows; row++)
- {
- rect.top = rect.bottom + 1;
- rect.bottom = rect.top + GetRowHeight(row) - 1;
- rect.right = -1;
- for (col = 0; col < m_nFixedCols; col++)
- {
- rect.left = rect.right + 1;
- rect.right = rect.left + GetColumnWidth(col) - 1;
- pCell = GetCell(row, col);
- if (pCell)
- pCell->Draw(pDC, row, col, rect, FALSE);
- }
- }
- // draw fixed column cells: m_nFixedRows..n, 0..m_nFixedCols-1
- rect.bottom = nFixedRowHeight - 1;
- for (row = minVisibleRow; row <= maxVisibleRow; row++)
- {
- rect.top = rect.bottom + 1;
- rect.bottom = rect.top + GetRowHeight(row) - 1;
- // rect.bottom = bottom pixel of previous row
- if (rect.top > clipRect.bottom)
- break; // Gone past cliprect
- if (rect.bottom < clipRect.top)
- continue; // Reached cliprect yet?
- rect.right = -1;
- for (col = 0; col < m_nFixedCols; col++)
- {
- rect.left = rect.right + 1;
- rect.right = rect.left + GetColumnWidth(col) - 1;
- if (rect.left > clipRect.right)
- break; // gone past cliprect
- if (rect.right < clipRect.left)
- continue; // Reached cliprect yet?
- pCell = GetCell(row, col);
- if (pCell)
- pCell->Draw(pDC, row, col, rect, FALSE);
- }
- }
- // draw fixed row cells 0..m_nFixedRows, m_nFixedCols..n
- rect.bottom = -1;
- for (row = 0; row < m_nFixedRows; row++)
- {
- rect.top = rect.bottom + 1;
- rect.bottom = rect.top + GetRowHeight(row) - 1;
- // rect.bottom = bottom pixel of previous row
- if (rect.top > clipRect.bottom)
- break; // Gone past cliprect
- if (rect.bottom < clipRect.top)
- continue; // Reached cliprect yet?
- rect.right = nFixedColWidth - 1;
- for (col = minVisibleCol; col <= maxVisibleCol; col++)
- {
- rect.left = rect.right + 1;
- rect.right = rect.left + GetColumnWidth(col) - 1;
- if (rect.left > clipRect.right)
- break; // gone past cliprect
- if (rect.right < clipRect.left)
- continue; // Reached cliprect yet?
- pCell = GetCell(row, col);
- if (pCell)
- pCell->Draw(pDC, row, col, rect, FALSE);
- }
- }
- // draw rest of non-fixed cells
- rect.bottom = nFixedRowHeight - 1;
- for (row = minVisibleRow; row <= maxVisibleRow; row++)
- {
- rect.top = rect.bottom + 1;
- rect.bottom = rect.top + GetRowHeight(row) - 1;
- // rect.bottom = bottom pixel of previous row
- if (rect.top > clipRect.bottom)
- break; // Gone past cliprect
- if (rect.bottom < clipRect.top)
- continue; // Reached cliprect yet?
- rect.right = nFixedColWidth - 1;
- for (col = minVisibleCol; col <= maxVisibleCol; col++)
- {
- rect.left = rect.right + 1;
- rect.right = rect.left + GetColumnWidth(col) - 1;
- if (rect.left > clipRect.right)
- break; // gone past cliprect
- if (rect.right < clipRect.left)
- continue; // Reached cliprect yet?
- pCell = GetCell(row, col);
- // TRACE(_T("Cell %d,%d type: %s\n"), row, col, pCell->GetRuntimeClass()->m_lpszClassName);
- if (pCell)
- pCell->Draw(pDC, row, col, rect, FALSE);
- }
- }
- CPen pen;
- pen.CreatePen(PS_SOLID, 0, m_crGridLineColour);
- pDC->SelectObject(&pen);
- // draw vertical lines (drawn at ends of cells)
- if (m_nGridLines == GVL_BOTH || m_nGridLines == GVL_VERT)
- {
- int x = nFixedColWidth;
- for (col = minVisibleCol; col <= maxVisibleCol; col++)
- {
- x += GetColumnWidth(col);
- pDC->MoveTo(x - 1, nFixedRowHeight);
- pDC->LineTo(x - 1, VisRect.bottom);
- }
- }
- // draw horizontal lines (drawn at bottom of each cell)
- if (m_nGridLines == GVL_BOTH || m_nGridLines == GVL_HORZ)
- {
- int y = nFixedRowHeight;
- for (row = minVisibleRow; row <= maxVisibleRow; row++)
- {
- y += GetRowHeight(row);
- pDC->MoveTo(nFixedColWidth, y - 1);
- pDC->LineTo(VisRect.right, y - 1);
- }
- }
- pDC->SelectStockObject(NULL_PEN);
- // Let parent know it can discard it's data if it needs to.
- if (GetVirtualMode())
- SendCacheHintToParent(CCellRange(-1, -1, -1, -1));
- }
- ////////////////////////////////////////////////////////////////////////////////////////
- // CGridCtrl Cell selection stuff
- // Is a given cell designation valid (ie within the bounds of our number
- // of columns/rows)?
- BOOL CGridCtrl::IsValid(int nRow, int nCol) const
- {
- return (nRow >= 0 && nRow < m_nRows && nCol >= 0 && nCol < m_nCols);
- }
- BOOL CGridCtrl::IsValid(const CCellID& cell) const
- {
- return IsValid(cell.row, cell.col);
- }
- // Is a given cell range valid (ie within the bounds of our number
- // of columns/rows)?
- BOOL CGridCtrl::IsValid(const CCellRange& range) const
- {
- return (range.GetMinRow() >= 0 && range.GetMinCol() >= 0 &&
- range.GetMaxRow() >= 0 && range.GetMaxCol() >= 0 &&
- range.GetMaxRow() < m_nRows && range.GetMaxCol() < m_nCols &&
- range.GetMinRow() <= range.GetMaxRow() && range.GetMinCol() <= range.GetMaxCol());
- }
- // Enables/Disables redraw for certain operations like columns auto-sizing etc,
- // but not for user caused things such as selection changes.
- void CGridCtrl::SetRedraw(BOOL bAllowDraw, BOOL bResetScrollBars /* = FALSE */)
- {
- // TRACE(_T("%s: Setting redraw to %s\n"),
- // GetRuntimeClass()->m_lpszClassName, bAllowDraw? _T("TRUE") : _T("FALSE"));
- if (bAllowDraw && !m_bAllowDraw)
- {
- m_bAllowDraw = TRUE;
- Refresh();
- }
- m_bAllowDraw = bAllowDraw;
- if (bResetScrollBars)
- ResetScrollBars();
- }
- // Forces a redraw of a cell immediately (using a direct DC construction,
- // or the supplied dc)
- BOOL CGridCtrl::RedrawCell(const CCellID& cell, CDC* pDC /* = NULL */)
- {
- return RedrawCell(cell.row, cell.col, pDC);
- }
- BOOL CGridCtrl::RedrawCell(int nRow, int nCol, CDC* pDC /* = NULL */)
- {
- BOOL bResult = TRUE;
- BOOL bMustReleaseDC = FALSE;
- if (!m_bAllowDraw || !IsCellVisible(nRow, nCol))
- return FALSE;
- CRect rect;
- if (!GetCellRect(nRow, nCol, rect))
- return FALSE;
- if (!pDC)
- {
- pDC = GetDC();
- if (pDC)
- bMustReleaseDC = TRUE;
- }
- if (pDC)
- {
- // Redraw cells directly
- if (nRow < m_nFixedRows || nCol < m_nFixedCols)
- {
- CGridCellBase* pCell = GetCell(nRow, nCol);
- if (pCell)
- bResult = pCell->Draw(pDC, nRow, nCol, rect, TRUE);
- }
- else
- {
- CGridCellBase* pCell = GetCell(nRow, nCol);
- if (pCell)
- bResult = pCell->Draw(pDC, nRow, nCol, rect, TRUE);
- // Since we have erased the background, we will need to redraw the gridlines
- CPen pen;
- pen.CreatePen(PS_SOLID, 0, m_crGridLineColour);
- CPen* pOldPen = (CPen*)pDC->SelectObject(&pen);
- if (m_nGridLines == GVL_BOTH || m_nGridLines == GVL_HORZ)
- {
- pDC->MoveTo(rect.left, rect.bottom);
- pDC->LineTo(rect.right + 1, rect.bottom);
- }
- if (m_nGridLines == GVL_BOTH || m_nGridLines == GVL_VERT)
- {
- pDC->MoveTo(rect.right, rect.top);
- pDC->LineTo(rect.right, rect.bottom + 1);
- }
- pDC->SelectObject(pOldPen);
- }
- }
- else
- InvalidateRect(rect, TRUE); // Could not get a DC - invalidate it anyway
- // and hope that OnPaint manages to get one
- if (bMustReleaseDC)
- ReleaseDC(pDC);
- return bResult;
- }
- // redraw a complete row
- BOOL CGridCtrl::RedrawRow(int row)
- {
- BOOL bResult = TRUE;
- CDC* pDC = GetDC();
- for (int col = 0; col < GetColumnCount(); col++)
- bResult = RedrawCell(row, col, pDC) && bResult;
- if (pDC)
- ReleaseDC(pDC);
- return bResult;
- }
- // redraw a complete column
- BOOL CGridCtrl::RedrawColumn(int col)
- {
- BOOL bResult = TRUE;
- CDC* pDC = GetDC();
- for (int row = 0; row < GetRowCount(); row++)
- bResult = RedrawCell(row, col, pDC) && bResult;
- if (pDC)
- ReleaseDC(pDC);
- return bResult;
- }
- // Sets the currently selected cell, returning the previous current cell
- CCellID CGridCtrl::SetFocusCell(int nRow, int nCol)
- {
- return SetFocusCell(CCellID(nRow, nCol));
- }
- CCellID CGridCtrl::SetFocusCell(CCellID cell)
- {
- if (cell == m_idCurrentCell)
- return m_idCurrentCell;
- CCellID idPrev = m_idCurrentCell;
- // EFW - Bug Fix - Force focus to be in a non-fixed cell
- if (cell.row != -1 && cell.row < GetFixedRowCount())
- cell.row = GetFixedRowCount();
- if (cell.col != -1 && cell.col < GetFixedColumnCount())
- cell.col = GetFixedColumnCount();
- m_idCurrentCell = cell;
- if (IsValid(idPrev))
- {
- SetItemState(idPrev.row, idPrev.col,
- GetItemState(idPrev.row, idPrev.col) & ~GVIS_FOCUSED);
- RedrawCell(idPrev); // comment to reduce flicker
- if (GetTrackFocusCell() && idPrev.col != m_idCurrentCell.col)
- for (int row = 0; row < m_nFixedRows; row++)
- RedrawCell(row, idPrev.col);
- if (GetTrackFocusCell() && idPrev.row != m_idCurrentCell.row)
- for (int col = 0; col < m_nFixedCols; col++)
- RedrawCell(idPrev.row, col);
- }
- if (IsValid(m_idCurrentCell))
- {
- SetItemState(m_idCurrentCell.row, m_idCurrentCell.col,
- GetItemState(m_idCurrentCell.row, m_idCurrentCell.col) | GVIS_FOCUSED);
- RedrawCell(m_idCurrentCell); // comment to reduce flicker
- if (GetTrackFocusCell() && idPrev.col != m_idCurrentCell.col)
- for (int row = 0; row < m_nFixedRows; row++)
- RedrawCell(row, m_idCurrentCell.col);
- if (GetTrackFocusCell() && idPrev.row != m_idCurrentCell.row)
- for (int col = 0; col < m_nFixedCols; col++)
- RedrawCell(m_idCurrentCell.row, col);
- // EFW - New addition. If in list mode, make sure the selected
- // row highlight follows the cursor.
- // Removed by C Maunder 27 May
- //if (m_bListMode)
- //{
- // m_PrevSelectedCellMap.RemoveAll();
- // m_MouseMode = MOUSE_SELECT_ROW;
- // OnSelecting(m_idCurrentCell);
- // Leave this off so that you can still drag the highlight around
- // without selecting rows.
- // m_MouseMode = MOUSE_NOTHING;
- //}
- }
- return idPrev;
- }
- // Sets the range of currently selected cells
- void CGridCtrl::SetSelectedRange(const CCellRange& Range,
- BOOL bForceRepaint /* = FALSE */, BOOL bSelectCells/*=TRUE*/)
- {
- SetSelectedRange(Range.GetMinRow(), Range.GetMinCol(),
- Range.GetMaxRow(), Range.GetMaxCol(),
- bForceRepaint, bSelectCells);
- }
- void CGridCtrl::SetSelectedRange(int nMinRow, int nMinCol, int nMaxRow, int nMaxCol,
- BOOL bForceRepaint /* = FALSE */, BOOL bSelectCells/*=TRUE*/)
- {
- if (!m_bEnableSelection)
- return;
- CDC* pDC = NULL;
- if (bForceRepaint)
- pDC = GetDC();
- // Only redraw visible cells
- CCellRange VisCellRange;
- if (IsWindow(GetSafeHwnd()))
- VisCellRange = GetVisibleNonFixedCellRange();
- // EFW - Bug fix - Don't allow selection of fixed rows
- if (nMinRow >= 0 && nMinRow < GetFixedRowCount())
- nMinRow = GetFixedRowCount();
- if (nMaxRow >= 0 && nMaxRow < GetFixedRowCount())
- nMaxRow = GetFixedRowCount();
- if (nMinCol >= 0 && nMinCol < GetFixedColumnCount())
- nMinCol = GetFixedColumnCount();
- if (nMaxCol >= 0 && nMaxCol < GetFixedColumnCount())
- nMaxCol = GetFixedColumnCount();
- // If we are selecting cells, then first clear out the list of currently selected cells, then
- if (bSelectCells)
- {
- POSITION pos;
- // Unselect all previously selected cells
- for (pos = m_SelectedCellMap.GetStartPosition(); pos != NULL;)
- {
- DWORD key;
- CCellID cell;
- m_SelectedCellMap.GetNextAssoc(pos, key, (CCellID&)cell);
- // Reset the selection flag on the cell
- if (IsValid(cell))
- {
- // This will remove the cell from the m_SelectedCellMap map
- SetItemState(cell.row, cell.col,
- GetItemState(cell.row, cell.col) & ~GVIS_SELECTED);
- // If this is to be reselected, continue on past the redraw
- if (nMinRow <= cell.row && cell.row <= nMaxRow &&
- nMinCol <= cell.col && cell.col <= nMaxCol)
- continue;
- if (VisCellRange.IsValid() && VisCellRange.InRange(cell))
- {
- if (bForceRepaint && pDC) // Redraw NOW
- RedrawCell(cell.row, cell.col, pDC);
- else
- InvalidateCellRect(cell); // Redraw at leisure
- }
- }
- else
- {
- m_SelectedCellMap.RemoveKey(key); // if it's not valid, get rid of it!
- }
- }
- // if we are selecting cells, and there are previous selected cells to be retained
- // (eg Ctrl is being held down) then copy them to the newly created list, and mark
- // all these cells as selected
- // Note that if we are list mode, single row selection, the we won't be adding
- // the previous cells. Only the current row of cells will be added (see below)
- if (!GetSingleRowSelection() &&
- nMinRow >= 0 && nMinCol >= 0 && nMaxRow >= 0 && nMaxCol >= 0)
- {
- for (pos = m_PrevSelectedCellMap.GetStartPosition(); pos != NULL; /* nothing */)
- {
- DWORD key;
- CCellID cell;
- m_PrevSelectedCellMap.GetNextAssoc(pos, key, (CCellID&)cell);
- if (!IsValid(cell))
- continue;
- int nState = GetItemState(cell.row, cell.col);
- // Set state as Selected. This will add the cell to m_SelectedCellMap
- SetItemState(cell.row, cell.col, nState | GVIS_SELECTED);
- if (VisCellRange.IsValid() && VisCellRange.InRange(cell))
- {
- // Redraw (immediately or at leisure)
- if (bForceRepaint && pDC)
- RedrawCell(cell.row, cell.col, pDC);
- else
- InvalidateCellRect(cell);
- }
- }
- }
- }
- // Now select/deselect all cells in the cell range specified. If selecting, and the cell
- // has already been marked as selected (above) then ignore it. If we are deselecting and
- // the cell isn't selected, then ignore
- if (nMinRow >= 0 && nMinCol >= 0 && nMaxRow >= 0 && nMaxCol >= 0 &&
- nMaxRow < m_nRows && nMaxCol < m_nCols &&
- nMinRow <= nMaxRow && nMinCol <= nMaxCol)
- {
- for (int row = nMinRow; row <= nMaxRow; row++)
- for (int col = nMinCol; col <= nMaxCol; col++)
- {
- int nState = GetItemState(row, col);
- // Why is there no XOR operator in C??? We have bitwise XOR ^, but what about ^^??
- if ((bSelectCells && (nState & GVIS_SELECTED)) ||
- (!bSelectCells && !(nState & GVIS_SELECTED)))
- continue; // Already selected or deselected - ignore
- // Set the selected state. This will add/remove the cell to m_SelectedCellMap
- if (bSelectCells)
- SetItemState(row, col, nState | GVIS_SELECTED);
- else
- SetItemState(row, col, GetItemState(row, col) & ~GVIS_SELECTED);
- if (VisCellRange.IsValid() && VisCellRange.InRange(row, col))
- {
- // Redraw (immediately or at leisure)
- if (bForceRepaint && pDC)
- RedrawCell(row, col, pDC);
- else
- InvalidateCellRect(row, col);
- }
- }
- }
- // TRACE(_T("%d cells selected.\n"), m_SelectedCellMap.GetCount());
- if (pDC != NULL)
- ReleaseDC(pDC);
- }
- // selects all cells
- void CGridCtrl::SelectAllCells()
- {
- if (!m_bEnableSelection)
- return;
- SetSelectedRange(m_nFixedRows, m_nFixedCols, GetRowCount() - 1, GetColumnCount() - 1);
- }
- // selects columns
- void CGridCtrl::SelectColumns(CCellID currentCell,
- BOOL bForceRedraw /*=FALSE*/, BOOL bSelectCells /*=TRUE*/)
- {
- if (!m_bEnableSelection)
- return;
- //if (currentCell.col == m_idCurrentCell.col) return;
- if (currentCell.col < m_nFixedCols)
- return;
- if (!IsValid(currentCell))
- return;
- if (GetSingleColSelection())
- SetSelectedRange(GetFixedRowCount(), currentCell.col,
- GetRowCount() - 1, currentCell.col,
- bForceRedraw, bSelectCells);
- else
- SetSelectedRange(GetFixedRowCount(),
- min(m_SelectionStartCell.col, currentCell.col),
- GetRowCount() - 1,
- max(m_SelectionStartCell.col, currentCell.col),
- bForceRedraw, bSelectCells);
- }
- // selects rows
- void CGridCtrl::SelectRows(CCellID currentCell,
- BOOL bForceRedraw /*=FALSE*/, BOOL bSelectCells /*=TRUE*/)
- {
- if (!m_bEnableSelection)
- return;
- //if (currentCell.row; == m_idCurrentCell.row) return;
- if (currentCell.row < m_nFixedRows)
- return;
- if (!IsValid(currentCell))
- return;
- if (GetSingleRowSelection())
- SetSelectedRange(currentCell.row, GetFixedColumnCount(),
- currentCell.row, GetColumnCount() - 1,
- bForceRedraw, bSelectCells);
- else
- SetSelectedRange(min(m_SelectionStartCell.row, currentCell.row),
- GetFixedColumnCount(),
- max(m_SelectionStartCell.row, currentCell.row),
- GetColumnCount() - 1,
- bForceRedraw, bSelectCells);
- }
- // selects cells
- void CGridCtrl::SelectCells(CCellID currentCell,
- BOOL bForceRedraw /*=FALSE*/, BOOL bSelectCells /*=TRUE*/)
- {
- if (!m_bEnableSelection)
- return;
- int row = currentCell.row;
- int col = currentCell.col;
- if (row < m_nFixedRows || col < m_nFixedCols)
- return;
- if (!IsValid(currentCell))
- return;
- // Prevent unnecessary redraws
- //if (currentCell == m_LeftClickDownCell) return;
- //else if (currentCell == m_idCurrentCell) return;
- SetSelectedRange(min(m_SelectionStartCell.row, row),
- min(m_SelectionStartCell.col, col),
- max(m_SelectionStartCell.row, row),
- max(m_SelectionStartCell.col, col),
- bForceRedraw, bSelectCells);
- }
- // Called when mouse/keyboard selection is a-happening.
- void CGridCtrl::OnSelecting(const CCellID& currentCell)
- {
- if (!m_bEnableSelection)
- return;
- switch (m_MouseMode)
- {
- case MOUSE_SELECT_ALL:
- SelectAllCells();
- break;
- case MOUSE_SELECT_COL:
- SelectColumns(currentCell, FALSE);
- break;
- case MOUSE_SELECT_ROW:
- SelectRows(currentCell, FALSE);
- break;
- case MOUSE_SELECT_CELLS:
- SelectCells(currentCell, FALSE);
- break;
- }
- // EFW - Bug fix [REMOVED CJM: this will cause infinite loop in list mode]
- // SetFocusCell(max(currentCell.row, m_nFixedRows), max(currentCell.col, m_nFixedCols));
- }
- void CGridCtrl::ValidateAndModifyCellContents(int nRow, int nCol, LPCTSTR strText)
- {
- if (!IsCellEditable(nRow, nCol))
- return;
- if (SendMessageToParent(nRow, nCol, GVN_BEGINLABELEDIT) >= 0)
- {
- CString strCurrentText = GetItemText(nRow, nCol);
- if (strCurrentText != strText)
- {
- SetItemText(nRow, nCol, strText);
- if (ValidateEdit(nRow, nCol, strText) &&
- SendMessageToParent(nRow, nCol, GVN_ENDLABELEDIT) >= 0)
- {
- SetModified(TRUE, nRow, nCol);
- RedrawCell(nRow, nCol);
- }
- else
- {
- SetItemText(nRow, nCol, strCurrentText);
- }
- }
- }
- }
- void CGridCtrl::ClearCells(CCellRange Selection)
- {
- for (int row = Selection.GetMinRow(); row <= Selection.GetMaxRow(); row++)
- {
- for (int col = Selection.GetMinCol(); col <= Selection.GetMaxCol(); col++)
- {
- // don't clear hidden cells
- if (m_arRowHeights[row] > 0 && m_arColWidths[col] > 0)
- {
- ValidateAndModifyCellContents(row, col, _T(""));
- }
- }
- }
- Refresh();
- }
- #ifndef GRIDCONTROL_NO_CLIPBOARD
- ////////////////////////////////////////////////////////////////////////////////////////
- // Clipboard functions
- // Deletes the contents from the selected cells
- void CGridCtrl::CutSelectedText()
- {
- if (!IsEditable())
- return;
- CCellRange Selection = GetSelectedCellRange();
- if (!IsValid(Selection))
- return;
- ClearCells(Selection);
- }
- // Copies text from the selected cells to the clipboard
- COleDataSource* CGridCtrl::CopyTextFromGrid()
- {
- USES_CONVERSION;
- CCellRange Selection = GetSelectedCellRange();
- if (!IsValid(Selection))
- return NULL;
- if (GetVirtualMode())
- SendCacheHintToParent(Selection);
- // Write to shared file (REMEBER: CF_TEXT is ANSI, not UNICODE, so we need to convert)
- CSharedFile sf(GMEM_MOVEABLE | GMEM_DDESHARE | GMEM_ZEROINIT);
- // Get a tab delimited string to copy to cache
- CString str;
- CGridCellBase *pCell;
- for (int row = Selection.GetMinRow(); row <= Selection.GetMaxRow(); row++)
- {
- // don't copy hidden cells
- if (m_arRowHeights[row] <= 0)
- continue;
- str.Empty();
- for (int col = Selection.GetMinCol(); col <= Selection.GetMaxCol(); col++)
- {
- // don't copy hidden cells
- if (m_arColWidths[col] <= 0)
- continue;
- pCell = GetCell(row, col);
- if (pCell && (pCell->GetState() & GVIS_SELECTED))
- {
- // if (!pCell->GetText())
- // str += _T(" ");
- // else
- str += pCell->GetText();
- }
- if (col != Selection.GetMaxCol())
- str += _T("\t");
- }
- if (row != Selection.GetMaxRow())
- str += _T("\n");
- sf.Write(T2A(str.GetBuffer(1)), str.GetLength());
- str.ReleaseBuffer();
- }
- char c = '\0';
- sf.Write(&c, 1);
- if (GetVirtualMode())
- SendCacheHintToParent(CCellRange(-1, -1, -1, -1));
- DWORD dwLen = (DWORD)sf.GetLength();
- HGLOBAL hMem = sf.Detach();
- if (!hMem)
- return NULL;
- hMem = ::GlobalReAlloc(hMem, dwLen, GMEM_MOVEABLE | GMEM_DDESHARE | GMEM_ZEROINIT);
- if (!hMem)
- return NULL;
- // Cache data
- COleDataSource* pSource = new COleDataSource();
- pSource->CacheGlobalData(CF_TEXT, hMem);
- return pSource;
- }
- // Pastes text from the clipboard to the selected cells
- BOOL CGridCtrl::PasteTextToGrid(CCellID cell, COleDataObject* pDataObject)
- {
- if (!IsValid(cell) || !IsCellEditable(cell) || !pDataObject->IsDataAvailable(CF_TEXT))
- return FALSE;
- // Get the text from the COleDataObject
- // Ñ¡ÔñºÏÊʵĸñʽ;
- UINT uiFormat = (sizeof(TCHAR)==sizeof(WCHAR)) ? CF_UNICODETEXT : CF_TEXT;
- HGLOBAL hmem = pDataObject->GetGlobalData(uiFormat); // CF_TEXT
- CMemFile sf((BYTE*) ::GlobalLock(hmem), ::GlobalSize(hmem));
- // CF_TEXT is ANSI text, so we need to allocate a char* buffer
- // to hold this.
- LPTSTR szBuffer = new TCHAR[::GlobalSize(hmem)];
- if (!szBuffer)
- return FALSE;
- sf.Read(szBuffer, ::GlobalSize(hmem));
- ::GlobalUnlock(hmem);
- // Now store in generic TCHAR form so we no longer have to deal with
- // ANSI/UNICODE problems
- CString strText = szBuffer;
- delete szBuffer;
- // Parse text data and set in cells...
- strText.LockBuffer();
- CString strLine = strText;
- int nLine = 0;
- // Find the end of the first line
- int nIndex;
- do
- {
- int nColumn = 0;
- nIndex = strLine.Find(_T("\n"));
- // Store the remaining chars after the newline
- CString strNext = (nIndex < 0) ? _T("") : strLine.Mid(nIndex + 1);
- // Remove all chars after the newline
- if (nIndex >= 0)
- strLine = strLine.Left(nIndex);
- int nLineIndex = strLine.FindOneOf(_T("\t,"));
- CString strCellText = (nLineIndex >= 0) ? strLine.Left(nLineIndex) : strLine;
- // skip hidden rows
- int iRowVis = cell.row + nLine;
- while (iRowVis < GetRowCount())
- {
- if (GetRowHeight(iRowVis) > 0)
- break;
- nLine++;
- iRowVis++;
- }
- while (!strLine.IsEmpty())
- {
- // skip hidden columns
- int iColVis = cell.col + nColumn;
- while (iColVis < GetColumnCount())
- {
- if (GetColumnWidth(iColVis) > 0)
- break;
- nColumn++;
- iColVis++;
- }
- CCellID TargetCell(iRowVis, iColVis);
- if (IsValid(TargetCell))
- {
- strCellText.TrimLeft();
- strCellText.TrimRight();
- ValidateAndModifyCellContents(TargetCell.row, TargetCell.col, strCellText);
- // Make sure cell is not selected to avoid data loss
- SetItemState(TargetCell.row, TargetCell.col,
- GetItemState(TargetCell.row, TargetCell.col) & ~GVIS_SELECTED);
- }
- strLine = (nLineIndex >= 0) ? strLine.Mid(nLineIndex + 1) : _T("");
- nLineIndex = strLine.FindOneOf(_T("\t,"));
- strCellText = (nLineIndex >= 0) ? strLine.Left(nLineIndex) : strLine;
- nColumn++;
- }
- strLine = strNext;
- nLine++;
- } while (nIndex >= 0);
- strText.UnlockBuffer();
- Refresh();
- return TRUE;
- }
- #endif
- #ifndef GRIDCONTROL_NO_DRAGDROP
- // Start drag n drop
- void CGridCtrl::OnBeginDrag()
- {
- if (!m_bAllowDragAndDrop)
- return;
- COleDataSource* pSource = CopyTextFromGrid();
- if (pSource)
- {
- SendMessageToParent(GetSelectedCellRange().GetTopLeft().row,
- GetSelectedCellRange().GetTopLeft().col,
- GVN_BEGINDRAG);
- m_MouseMode = MOUSE_DRAGGING;
- m_bLMouseButtonDown = FALSE;
- DROPEFFECT dropEffect = pSource->DoDragDrop(DROPEFFECT_COPY | DROPEFFECT_MOVE);
- if (dropEffect & DROPEFFECT_MOVE)
- CutSelectedText();
- if (pSource)
- delete pSource; // Did not pass source to clipboard, so must delete
- }
- }
- // Handle drag over grid
- DROPEFFECT CGridCtrl::OnDragOver(COleDataObject* pDataObject, DWORD dwKeyState,
- CPoint point)
- {
- // Any text data available for us?
- if (!m_bAllowDragAndDrop || !IsEditable() || !pDataObject->IsDataAvailable(CF_TEXT))
- return DROPEFFECT_NONE;
- // Find which cell we are over and drop-highlight it
- CCellID cell = GetCellFromPt(point, FALSE);
- // If not valid, set the previously drop-highlighted cell as no longer drop-highlighted
- if (!IsValid(cell))
- {
- OnDragLeave();
- m_LastDragOverCell = CCellID(-1, -1);
- return DROPEFFECT_NONE;
- }
- if (!IsCellEditable(cell))
- return DROPEFFECT_NONE;
- // Have we moved over a different cell than last time?
- if (cell != m_LastDragOverCell)
- {
- // Set the previously drop-highlighted cell as no longer drop-highlighted
- if (IsValid(m_LastDragOverCell))
- {
- UINT nState = GetItemState(m_LastDragOverCell.row, m_LastDragOverCell.col);
- SetItemState(m_LastDragOverCell.row, m_LastDragOverCell.col,
- nState & ~GVIS_DROPHILITED);
- RedrawCell(m_LastDragOverCell);
- }
- m_LastDragOverCell = cell;
- // Set the new cell as drop-highlighted
- if (IsValid(m_LastDragOverCell))
- {
- UINT nState = GetItemState(m_LastDragOverCell.row, m_LastDragOverCell.col);
- SetItemState(m_LastDragOverCell.row, m_LastDragOverCell.col,
- nState | GVIS_DROPHILITED);
- RedrawCell(m_LastDragOverCell);
- }
- }
- // Return an appropraite value of DROPEFFECT so mouse cursor is set properly
- if (dwKeyState & MK_CONTROL)
- return DROPEFFECT_COPY;
- else
- return DROPEFFECT_MOVE;
- }
- // Something has just been dragged onto the grid
- DROPEFFECT CGridCtrl::OnDragEnter(COleDataObject* pDataObject, DWORD dwKeyState,
- CPoint point)
- {
- // Any text data available for us?
- if (!m_bAllowDragAndDrop || !pDataObject->IsDataAvailable(CF_TEXT))
- return DROPEFFECT_NONE;
- // Find which cell we are over and drop-highlight it
- m_LastDragOverCell = GetCellFromPt(point, FALSE);
- if (!IsValid(m_LastDragOverCell))
- return DROPEFFECT_NONE;
- if (!IsCellEditable(m_LastDragOverCell))
- return DROPEFFECT_NONE;
- if (IsValid(m_LastDragOverCell))
- {
- UINT nState = GetItemState(m_LastDragOverCell.row, m_LastDragOverCell.col);
- SetItemState(m_LastDragOverCell.row, m_LastDragOverCell.col,
- nState | GVIS_DROPHILITED);
- RedrawCell(m_LastDragOverCell);
- }
- // Return an appropraite value of DROPEFFECT so mouse cursor is set properly
- if (dwKeyState & MK_CONTROL)
- return DROPEFFECT_COPY;
- else
- return DROPEFFECT_MOVE;
- }
- // Something has just been dragged away from the grid
- void CGridCtrl::OnDragLeave()
- {
- // Set the previously drop-highlighted cell as no longer drop-highlighted
- if (IsValid(m_LastDragOverCell))
- {
- UINT nState = GetItemState(m_LastDragOverCell.row, m_LastDragOverCell.col);
- SetItemState(m_LastDragOverCell.row, m_LastDragOverCell.col,
- nState & ~GVIS_DROPHILITED);
- RedrawCell(m_LastDragOverCell);
- }
- }
- // Something has just been dropped onto the grid
- BOOL CGridCtrl::OnDrop(COleDataObject* pDataObject, DROPEFFECT /*dropEffect*/,
- CPoint /* point */)
- {
- m_MouseMode = MOUSE_NOTHING;
- if (!m_bAllowDragAndDrop || !IsCellEditable(m_LastDragOverCell))
- return FALSE;
- OnDragLeave();
- return PasteTextToGrid(m_LastDragOverCell, pDataObject);
- }
- #endif
- #ifndef GRIDCONTROL_NO_CLIPBOARD
- void CGridCtrl::OnEditCut()
- {
- if (!IsEditable())
- return;
- COleDataSource* pSource = CopyTextFromGrid();
- if (!pSource)
- return;
- pSource->SetClipboard();
- CutSelectedText();
- }
- void CGridCtrl::OnEditCopy()
- {
- COleDataSource* pSource = CopyTextFromGrid();
- if (!pSource)
- return;
- pSource->SetClipboard();
- }
- void CGridCtrl::OnEditPaste()
- {
- if (!IsEditable())
- return;
- // Get the Focus cell, or if none, get the topleft (non-fixed) cell
- CCellID cell = GetFocusCell();
- if (!IsValid(cell))
- cell = GetTopleftNonFixedCell();
- if (!IsValid(cell))
- return;
- // If a cell is being edited, then call it's edit window paste function.
- if (IsItemEditing(cell.row, cell.col))
- {
- CGridCellBase* pCell = GetCell(cell.row, cell.col);
- ASSERT(pCell);
- if (!pCell) return;
- CWnd* pEditWnd = pCell->GetEditWnd();
- if (pEditWnd && pEditWnd->IsKindOf(RUNTIME_CLASS(CEdit)))
- {
- ((CEdit*)pEditWnd)->Paste();
- return;
- }
- }
- // Attach a COleDataObject to the clipboard and paste the data to the grid
- COleDataObject obj;
- if (obj.AttachClipboard())
- PasteTextToGrid(cell, &obj);
- }
- #endif
- void CGridCtrl::OnEditSelectAll()
- {
- SendMessageToParent(m_LeftClickDownCell.row, m_LeftClickDownCell.col, GVN_SELCHANGING);
- SelectAllCells();
- SendMessageToParent(m_idCurrentCell.row, m_idCurrentCell.col, GVN_SELCHANGED);
- }
- #ifndef GRIDCONTROL_NO_CLIPBOARD
- void CGridCtrl::OnUpdateEditCopy(CCmdUI* pCmdUI)
- {
- CCellRange Selection = GetSelectedCellRange();
- pCmdUI->Enable(Selection.Count() && IsValid(Selection));
- }
- void CGridCtrl::OnUpdateEditCut(CCmdUI* pCmdUI)
- {
- CCellRange Selection = GetSelectedCellRange();
- pCmdUI->Enable(IsEditable() && Selection.Count() && IsValid(Selection));
- }
- void CGridCtrl::OnUpdateEditPaste(CCmdUI* pCmdUI)
- {
- CCellID cell = GetFocusCell();
- BOOL bCanPaste = IsValid(cell) && IsCellEditable(cell) &&
- ::IsClipboardFormatAvailable(CF_TEXT);
- pCmdUI->Enable(bCanPaste);
- }
- #endif
- void CGridCtrl::OnUpdateEditSelectAll(CCmdUI* pCmdUI)
- {
- pCmdUI->Enable(m_bEnableSelection);
- }
- ////////////////////////////////////////////////////////////////////////////////////////
- // hittest-like functions
- // TRUE if the mouse is over a row resize area
- BOOL CGridCtrl::MouseOverRowResizeArea(CPoint& point)
- {
- if (point.x >= GetFixedColumnWidth())
- return FALSE;
- CCellID idCurrentCell = GetCellFromPt(point);
- CPoint start;
- if (!GetCellOrigin(idCurrentCell, &start))
- return FALSE;
- int endy = start.y + GetRowHeight(idCurrentCell.row);
- if ((point.y - start.y < m_nResizeCaptureRange && idCurrentCell.row != 0) ||
- endy - point.y < m_nResizeCaptureRange)
- {
- return TRUE;
- }
- else
- return FALSE;
- }
- // TRUE if the mouse is over a column resize area. point is in Client coords
- BOOL CGridCtrl::MouseOverColumnResizeArea(CPoint& point)
- {
- if (point.y >= GetFixedRowHeight())
- return FALSE;
- CCellID idCurrentCell = GetCellFromPt(point);
- CPoint start;
- if (!GetCellOrigin(idCurrentCell, &start))
- return FALSE;
- int endx = start.x + GetColumnWidth(idCurrentCell.col);
- if ((point.x - start.x < m_nResizeCaptureRange && idCurrentCell.col != 0) ||
- endx - point.x < m_nResizeCaptureRange)
- {
- return TRUE;
- }
- else
- return FALSE;
- }
- // Get cell from point.
- // point - client coordinates
- // bAllowFixedCellCheck - if TRUE then fixed cells are checked
- CCellID CGridCtrl::GetCellFromPt(CPoint point, BOOL bAllowFixedCellCheck /*=TRUE*/)
- {
- CCellID cellID; // return value
- CCellID idTopLeft = GetTopleftNonFixedCell();
- if (!bAllowFixedCellCheck && !IsValid(idTopLeft))
- return cellID;
- // calculate column index
- int fixedColWidth = GetFixedColumnWidth();
- if (point.x < 0 || (!bAllowFixedCellCheck && point.x < fixedColWidth)) // not in window
- cellID.col = -1;
- else if (point.x < fixedColWidth) // in fixed col
- {
- int xpos = 0;
- int col = 0;
- while (col < m_nFixedCols)
- {
- xpos += GetColumnWidth(col);
- if (xpos > point.x)
- break;
- col++;
- }
- cellID.col = col;
- }
- else // in non-fixed col
- {
- int xpos = fixedColWidth;
- int col = idTopLeft.col; //m_nFixedCols;
- while (col < GetColumnCount())
- {
- xpos += GetColumnWidth(col);
- if (xpos > point.x)
- break;
- col++;
- }
- if (col >= GetColumnCount())
- cellID.col = -1;
- else
- cellID.col = col;
- }
- // calculate row index
- int fixedRowHeight = GetFixedRowHeight();
- if (point.y < 0 || (!bAllowFixedCellCheck && point.y < fixedRowHeight)) // not in window
- cellID.row = -1;
- else if (point.y < fixedRowHeight) // in fixed col
- {
- int ypos = 0;
- int row = 0;
- while (row < m_nFixedRows)
- {
- ypos += GetRowHeight(row);
- if (ypos > point.y)
- break;
- row++;
- }
- cellID.row = row;
- }
- else
- {
- int ypos = fixedRowHeight;
- int row = idTopLeft.row; //m_nFixedRows;
- while (row < GetRowCount())
- {
- ypos += GetRowHeight(row);
- if (ypos > point.y)
- break;
- row++;
- }
- if (row >= GetRowCount())
- cellID.row = -1;
- else
- cellID.row = row;
- }
- return cellID;
- }
- ////////////////////////////////////////////////////////////////////////////////
- // CGridCtrl cellrange functions
- // Gets the first non-fixed cell ID
- CCellID CGridCtrl::GetTopleftNonFixedCell(BOOL bForceRecalculation /*=FALSE*/)
- {
- // Used cached value if possible
- if (m_idTopLeftCell.IsValid() && !bForceRecalculation)
- return m_idTopLeftCell;
- int nVertScroll = GetScrollPos(SB_VERT),
- nHorzScroll = GetScrollPos(SB_HORZ);
- m_idTopLeftCell.col = m_nFixedCols;
- int nRight = 0;
- while (nRight < nHorzScroll && m_idTopLeftCell.col < (GetColumnCount() - 1))
- nRight += GetColumnWidth(m_idTopLeftCell.col++);
- m_idTopLeftCell.row = m_nFixedRows;
- int nTop = 0;
- while (nTop < nVertScroll && m_idTopLeftCell.row < (GetRowCount() - 1))
- nTop += GetRowHeight(m_idTopLeftCell.row++);
- //TRACE2("TopLeft cell is row %d, col %d\n",m_idTopLeftCell.row, m_idTopLeftCell.col);
- return m_idTopLeftCell;
- }
- // This gets even partially visible cells
- CCellRange CGridCtrl::GetVisibleNonFixedCellRange(LPRECT pRect /*=NULL*/,
- BOOL bForceRecalculation /*=FALSE*/)
- {
- CRect rect;
- GetClientRect(rect);
- CCellID idTopLeft = GetTopleftNonFixedCell(bForceRecalculation);
- // calc bottom
- int i = 0;
- int bottom = GetFixedRowHeight();
- for (i = idTopLeft.row; i < GetRowCount(); i++)
- {
- bottom += GetRowHeight(i);
- if (bottom >= rect.bottom)
- {
- bottom = rect.bottom;
- break;
- }
- }
- int maxVisibleRow = min(i, GetRowCount() - 1);
- // calc right
- int right = GetFixedColumnWidth();
- for (i = idTopLeft.col; i < GetColumnCount(); i++)
- {
- right += GetColumnWidth(i);
- if (right >= rect.right)
- {
- right = rect.right;
- break;
- }
- }
- int maxVisibleCol = min(i, GetColumnCount() - 1);
- if (pRect)
- {
- pRect->left = pRect->top = 0;
- pRect->right = right;
- pRect->bottom = bottom;
- }
- return CCellRange(idTopLeft.row, idTopLeft.col, maxVisibleRow, maxVisibleCol);
- }
- // used by ResetScrollBars() - This gets only fully visible cells
- CCellRange CGridCtrl::GetUnobstructedNonFixedCellRange(BOOL bForceRecalculation /*=FALSE*/)
- {
- CRect rect;
- GetClientRect(rect);
- CCellID idTopLeft = GetTopleftNonFixedCell(bForceRecalculation);
- // calc bottom
- int i = 0;
- int bottom = GetFixedRowHeight();
- for (i = idTopLeft.row; i < GetRowCount(); i++)
- {
- bottom += GetRowHeight(i);
- if (bottom >= rect.bottom)
- break;
- }
- int maxVisibleRow = min(i, GetRowCount() - 1);
- if (maxVisibleRow > 0 && bottom > rect.bottom)
- maxVisibleRow--;
- // calc right
- int right = GetFixedColumnWidth();
- for (i = idTopLeft.col; i < GetColumnCount(); i++)
- {
- right += GetColumnWidth(i);
- if (right >= rect.right)
- break;
- }
- int maxVisibleCol = min(i, GetColumnCount() - 1);
- if (maxVisibleCol > 0 && right > rect.right)
- maxVisibleCol--;
- return CCellRange(idTopLeft.row, idTopLeft.col, maxVisibleRow, maxVisibleCol);
- }
- // Returns the minimum bounding range of the current selection
- // If no selection, then the returned CCellRange will be invalid
- CCellRange CGridCtrl::GetSelectedCellRange() const
- {
- CCellRange Selection(GetRowCount(), GetColumnCount(), -1, -1);
- for (POSITION pos = m_SelectedCellMap.GetStartPosition(); pos != NULL;)
- {
- DWORD key;
- CCellID cell;
- m_SelectedCellMap.GetNextAssoc(pos, key, (CCellID&)cell);
- Selection.SetMinRow(min(Selection.GetMinRow(), cell.row));
- Selection.SetMinCol(min(Selection.GetMinCol(), cell.col));
- Selection.SetMaxRow(max(Selection.GetMaxRow(), cell.row));
- Selection.SetMaxCol(max(Selection.GetMaxCol(), cell.col));
- }
- return Selection;
- }
- // Returns ALL the cells in the grid
- CCellRange CGridCtrl::GetCellRange() const
- {
- return CCellRange(0, 0, GetRowCount() - 1, GetColumnCount() - 1);
- }
- // Resets the selected cell range to the empty set.
- void CGridCtrl::ResetSelectedRange()
- {
- m_PrevSelectedCellMap.RemoveAll();
- SetSelectedRange(-1, -1, -1, -1);
- SetFocusCell(-1, -1);
- }
- // Get/Set scroll position using 32 bit functions
- int CGridCtrl::GetScrollPos32(int nBar, BOOL bGetTrackPos /* = FALSE */)
- {
- SCROLLINFO si;
- si.cbSize = sizeof(SCROLLINFO);
- if (bGetTrackPos)
- {
- if (GetScrollInfo(nBar, &si, SIF_TRACKPOS))
- return si.nTrackPos;
- }
- else
- {
- if (GetScrollInfo(nBar, &si, SIF_POS))
- return si.nPos;
- }
- return 0;
- }
- BOOL CGridCtrl::SetScrollPos32(int nBar, int nPos, BOOL bRedraw /* = TRUE */)
- {
- m_idTopLeftCell.row = -1;
- SCROLLINFO si;
- si.cbSize = sizeof(SCROLLINFO);
- si.fMask = SIF_POS;
- si.nPos = nPos;
- return SetScrollInfo(nBar, &si, bRedraw);
- }
- void CGridCtrl::EnableScrollBars(int nBar, BOOL bEnable /*=TRUE*/)
- {
- if (bEnable)
- {
- if (!IsVisibleHScroll() && (nBar == SB_HORZ || nBar == SB_BOTH))
- {
- CWnd::EnableScrollBarCtrl(SB_HORZ, bEnable);
- m_nBarState |= GVL_HORZ;
- }
- if (!IsVisibleVScroll() && (nBar == SB_VERT || nBar == SB_BOTH))
- {
- CWnd::EnableScrollBarCtrl(SB_VERT, bEnable);
- m_nBarState |= GVL_VERT;
- }
- }
- else
- {
- if (IsVisibleHScroll() && (nBar == SB_HORZ || nBar == SB_BOTH))
- {
- CWnd::EnableScrollBarCtrl(SB_HORZ, bEnable);
- m_nBarState &= ~GVL_HORZ;
- }
- if (IsVisibleVScroll() && (nBar == SB_VERT || nBar == SB_BOTH))
- {
- CWnd::EnableScrollBarCtrl(SB_VERT, bEnable);
- m_nBarState &= ~GVL_VERT;
- }
- }
- }
- // If resizing or cell counts/sizes change, call this - it'll fix up the scroll bars
- void CGridCtrl::ResetScrollBars()
- {
- // Force a refresh.
- m_idTopLeftCell.row = -1;
- if (!m_bAllowDraw || !::IsWindow(GetSafeHwnd()))
- return;
- CRect rect;
- // This would have caused OnSize event - Brian
- //EnableScrollBars(SB_BOTH, FALSE);
- GetClientRect(rect);
- if (rect.left == rect.right || rect.top == rect.bottom)
- return;
- if (IsVisibleVScroll())
- rect.right += GetSystemMetrics(SM_CXVSCROLL) + GetSystemMetrics(SM_CXBORDER);
- if (IsVisibleHScroll())
- rect.bottom += GetSystemMetrics(SM_CYHSCROLL) + GetSystemMetrics(SM_CYBORDER);
- rect.left += GetFixedColumnWidth();
- rect.top += GetFixedRowHeight();
- if (rect.left >= rect.right || rect.top >= rect.bottom)
- {
- EnableScrollBarCtrl(SB_BOTH, FALSE);
- return;
- }
- CRect VisibleRect(GetFixedColumnWidth(), GetFixedRowHeight(), rect.right, rect.bottom);
- CRect VirtualRect(GetFixedColumnWidth(), GetFixedRowHeight(), GetVirtualWidth(), GetVirtualHeight());
- // Removed to fix single row scrollbar problem (Pontus Goffe)
- // CCellRange visibleCells = GetUnobstructedNonFixedCellRange();
- // if (!IsValid(visibleCells)) return;
- //TRACE(_T("Visible: %d x %d, Virtual %d x %d. H %d, V %d\n"),
- // VisibleRect.Width(), VisibleRect.Height(),
- // VirtualRect.Width(), VirtualRect.Height(),
- // IsVisibleHScroll(), IsVisibleVScroll());
- // If vertical scroll bar, horizontal space is reduced
- if (VisibleRect.Height() < VirtualRect.Height())
- VisibleRect.right -= ::GetSystemMetrics(SM_CXVSCROLL);
- // If horz scroll bar, vert space is reduced
- if (VisibleRect.Width() < VirtualRect.Width())
- VisibleRect.bottom -= ::GetSystemMetrics(SM_CYHSCROLL);
- // Recheck vertical scroll bar
- //if (VisibleRect.Height() < VirtualRect.Height())
- // VisibleRect.right -= ::GetSystemMetrics(SM_CXVSCROLL);
- if (VisibleRect.Height() < VirtualRect.Height())
- {
- EnableScrollBars(SB_VERT, TRUE);
- m_nVScrollMax = VirtualRect.Height() - 1;
- }
- else
- {
- EnableScrollBars(SB_VERT, FALSE);
- m_nVScrollMax = 0;
- }
- if (VisibleRect.Width() < VirtualRect.Width())
- {
- EnableScrollBars(SB_HORZ, TRUE);
- m_nHScrollMax = VirtualRect.Width() - 1;
- }
- else
- {
- EnableScrollBars(SB_HORZ, FALSE);
- m_nHScrollMax = 0;
- }
- ASSERT(m_nVScrollMax < INT_MAX && m_nHScrollMax < INT_MAX); // This should be fine
- /* Old code - CJM
- SCROLLINFO si;
- si.cbSize = sizeof(SCROLLINFO);
- si.fMask = SIF_PAGE;
- si.nPage = (m_nHScrollMax>0)? VisibleRect.Width() : 0;
- SetScrollInfo(SB_HORZ, &si, FALSE);
- si.nPage = (m_nVScrollMax>0)? VisibleRect.Height() : 0;
- SetScrollInfo(SB_VERT, &si, FALSE);
- SetScrollRange(SB_VERT, 0, m_nVScrollMax, TRUE);
- SetScrollRange(SB_HORZ, 0, m_nHScrollMax, TRUE);
- */
- // New code - Paul Runstedler
- SCROLLINFO si;
- si.cbSize = sizeof(SCROLLINFO);
- si.fMask = SIF_PAGE | SIF_RANGE;
- si.nPage = (m_nHScrollMax > 0) ? VisibleRect.Width() : 0;
- si.nMin = 0;
- si.nMax = m_nHScrollMax;
- SetScrollInfo(SB_HORZ, &si, TRUE);
- si.fMask |= SIF_DISABLENOSCROLL;
- si.nPage = (m_nVScrollMax > 0) ? VisibleRect.Height() : 0;
- si.nMin = 0;
- si.nMax = m_nVScrollMax;
- SetScrollInfo(SB_VERT, &si, TRUE);
- }
- ////////////////////////////////////////////////////////////////////////////////////
- // Row/Column position functions
- // returns the top left point of the cell. Returns FALSE if cell not visible.
- BOOL CGridCtrl::GetCellOrigin(int nRow, int nCol, LPPOINT p)
- {
- int i;
- if (!IsValid(nRow, nCol))
- return FALSE;
- CCellID idTopLeft;
- if (nCol >= m_nFixedCols || nRow >= m_nFixedRows)
- idTopLeft = GetTopleftNonFixedCell();
- if ((nRow >= m_nFixedRows && nRow < idTopLeft.row) ||
- (nCol >= m_nFixedCols && nCol < idTopLeft.col))
- return FALSE;
- p->x = 0;
- if (nCol < m_nFixedCols) // is a fixed column
- for (i = 0; i < nCol; i++)
- p->x += GetColumnWidth(i);
- else
- { // is a scrollable data column
- for (i = 0; i < m_nFixedCols; i++)
- p->x += GetColumnWidth(i);
- for (i = idTopLeft.col; i < nCol; i++)
- p->x += GetColumnWidth(i);
- }
- p->y = 0;
- if (nRow < m_nFixedRows) // is a fixed row
- for (i = 0; i < nRow; i++)
- p->y += GetRowHeight(i);
- else
- { // is a scrollable data row
- for (i = 0; i < m_nFixedRows; i++)
- p->y += GetRowHeight(i);
- for (i = idTopLeft.row; i < nRow; i++)
- p->y += GetRowHeight(i);
- }
- return TRUE;
- }
- BOOL CGridCtrl::GetCellOrigin(const CCellID& cell, LPPOINT p)
- {
- return GetCellOrigin(cell.row, cell.col, p);
- }
- // Returns the bounding box of the cell
- BOOL CGridCtrl::GetCellRect(const CCellID& cell, LPRECT pRect)
- {
- return GetCellRect(cell.row, cell.col, pRect);
- }
- BOOL CGridCtrl::GetCellRect(int nRow, int nCol, LPRECT pRect)
- {
- CPoint CellOrigin;
- if (!GetCellOrigin(nRow, nCol, &CellOrigin))
- return FALSE;
- pRect->left = CellOrigin.x;
- pRect->top = CellOrigin.y;
- pRect->right = CellOrigin.x + GetColumnWidth(nCol) - 1;
- pRect->bottom = CellOrigin.y + GetRowHeight(nRow) - 1;
- //TRACE("Row %d, col %d: L %d, T %d, W %d, H %d: %d,%d - %d,%d\n",
- // nRow,nCol, CellOrigin.x, CellOrigin.y, GetColumnWidth(nCol), GetRowHeight(nRow),
- // pRect->left, pRect->top, pRect->right, pRect->bottom);
- return TRUE;
- }
- BOOL CGridCtrl::GetTextRect(const CCellID& cell, LPRECT pRect)
- {
- return GetTextRect(cell.row, cell.col, pRect);
- }
- BOOL CGridCtrl::GetTextRect(int nRow, int nCol, LPRECT pRect)
- {
- CGridCellBase* pCell = GetCell(nRow, nCol);
- if (pCell == NULL)
- return FALSE;
- if (!GetCellRect(nRow, nCol, pRect))
- return FALSE;
- return pCell->GetTextRect(pRect);
- }
- // Returns the bounding box of a range of cells
- BOOL CGridCtrl::GetCellRangeRect(const CCellRange& cellRange, LPRECT lpRect)
- {
- CPoint MinOrigin, MaxOrigin;
- if (!GetCellOrigin(cellRange.GetMinRow(), cellRange.GetMinCol(), &MinOrigin))
- return FALSE;
- if (!GetCellOrigin(cellRange.GetMaxRow(), cellRange.GetMaxCol(), &MaxOrigin))
- return FALSE;
- lpRect->left = MinOrigin.x;
- lpRect->top = MinOrigin.y;
- lpRect->right = MaxOrigin.x + GetColumnWidth(cellRange.GetMaxCol()) - 1;
- lpRect->bottom = MaxOrigin.y + GetRowHeight(cellRange.GetMaxRow()) - 1;
- return TRUE;
- }
- ////////////////////////////////////////////////////////////////////////////////////
- // Grid attribute functions
- LRESULT CGridCtrl::OnSetFont(WPARAM hFont, LPARAM /*lParam */)
- {
- LRESULT result = Default();
- // Get the logical font
- LOGFONT lf;
- if (!GetObject((HFONT)hFont, sizeof(LOGFONT), &lf))
- return result;
- m_cellDefault.SetFont(&lf);
- m_cellFixedColDef.SetFont(&lf);
- m_cellFixedRowDef.SetFont(&lf);
- m_cellFixedRowColDef.SetFont(&lf);
- Refresh();
- return result;
- }
- LRESULT CGridCtrl::OnGetFont(WPARAM /*wParam*/, LPARAM /*lParam*/)
- {
- //LOGFONT lf;
- //m_cellDefault.GetFontObject()->GetLogFont(&lf);
- return (LRESULT)m_cellDefault.GetFontObject()->GetSafeHandle();
- }
- #ifndef _WIN32_WCE_NO_CURSOR
- BOOL CGridCtrl::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
- {
- if (nHitTest == HTCLIENT)
- {
- switch (m_MouseMode)
- {
- case MOUSE_OVER_COL_DIVIDE:
- SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZEWE));
- break;
- case MOUSE_OVER_ROW_DIVIDE:
- SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZENS));
- break;
- #ifndef GRIDCONTROL_NO_DRAGDROP
- case MOUSE_DRAGGING:
- break;
- #endif
- default:
- if (!GetVirtualMode())
- {
- CPoint pt(GetMessagePos());
- ScreenToClient(&pt);
- CCellID cell = GetCellFromPt(pt);
- if (IsValid(cell))
- {
- CGridCellBase* pCell = GetCell(cell.row, cell.col);
- if (pCell)
- return pCell->OnSetCursor();
- }
- }
- SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
- }
- return TRUE;
- }
- return CWnd::OnSetCursor(pWnd, nHitTest, message);
- }
- #endif
- ////////////////////////////////////////////////////////////////////////////////////
- // Row/Column count functions
- BOOL CGridCtrl::SetFixedRowCount(int nFixedRows)
- {
- if (m_nFixedRows == nFixedRows)
- return TRUE;
- ASSERT(nFixedRows >= 0);
- ResetSelectedRange();
- // Force recalculation
- m_idTopLeftCell.col = -1;
- if (nFixedRows > GetRowCount())
- if (!SetRowCount(nFixedRows))
- return FALSE;
- if (m_idCurrentCell.row < nFixedRows)
- SetFocusCell(-1, -1);
- if (!GetVirtualMode())
- {
- if (nFixedRows > m_nFixedRows)
- {
- for (int i = m_nFixedRows; i < nFixedRows; i++)
- for (int j = 0; j < GetColumnCount(); j++)
- {
- SetItemState(i, j, GetItemState(i, j) | GVIS_FIXED | GVIS_FIXEDROW);
- SetItemBkColour(i, j, CLR_DEFAULT);
- SetItemFgColour(i, j, CLR_DEFAULT);
- }
- }
- else
- {
- for (int i = nFixedRows; i < m_nFixedRows; i++)
- {
- int j;
- for (j = 0; j < GetFixedColumnCount(); j++)
- SetItemState(i, j, GetItemState(i, j) & ~GVIS_FIXEDROW);
- for (j = GetFixedColumnCount(); j < GetColumnCount(); j++)
- {
- SetItemState(i, j, GetItemState(i, j) & ~(GVIS_FIXED | GVIS_FIXEDROW));
- SetItemBkColour(i, j, CLR_DEFAULT);
- SetItemFgColour(i, j, CLR_DEFAULT);
- }
- }
- }
- }
- m_nFixedRows = nFixedRows;
- Refresh();
- return TRUE;
- }
- BOOL CGridCtrl::SetFixedColumnCount(int nFixedCols)
- {
- if (m_nFixedCols == nFixedCols)
- return TRUE;
- ASSERT(nFixedCols >= 0);
- if (nFixedCols > GetColumnCount())
- if (!SetColumnCount(nFixedCols))
- return FALSE;
- if (m_idCurrentCell.col < nFixedCols)
- SetFocusCell(-1, -1);
- ResetSelectedRange();
- // Force recalculation
- m_idTopLeftCell.col = -1;
- if (!GetVirtualMode())
- {
- if (nFixedCols > m_nFixedCols)
- {
- for (int i = 0; i < GetRowCount(); i++)
- for (int j = m_nFixedCols; j < nFixedCols; j++)
- {
- SetItemState(i, j, GetItemState(i, j) | GVIS_FIXED | GVIS_FIXEDCOL);
- SetItemBkColour(i, j, CLR_DEFAULT);
- SetItemFgColour(i, j, CLR_DEFAULT);
- }
- }
- else
- {
- int i = 0;
- for (i = 0; i < GetFixedRowCount(); i++)
- for (int j = nFixedCols; j < m_nFixedCols; j++)
- SetItemState(i, j, GetItemState(i, j) & ~GVIS_FIXEDCOL);
- for (i = GetFixedRowCount(); i < GetRowCount(); i++)
- for (int j = nFixedCols; j < m_nFixedCols; j++)
- {
- SetItemState(i, j, GetItemState(i, j) & ~(GVIS_FIXED | GVIS_FIXEDCOL));
- SetItemBkColour(i, j, CLR_DEFAULT);
- SetItemFgColour(i, j, CLR_DEFAULT);
- }
- }
- }
- m_nFixedCols = nFixedCols;
- Refresh();
- return TRUE;
- }
- BOOL CGridCtrl::SetRowCount(int nRows)
- {
- BOOL bResult = TRUE;
- ASSERT(nRows >= 0);
- if (nRows == GetRowCount())
- return bResult;
- // Force recalculation
- m_idTopLeftCell.col = -1;
- if (nRows < m_nFixedRows)
- m_nFixedRows = nRows;
- if (m_idCurrentCell.row >= nRows)
- SetFocusCell(-1, -1);
- int addedRows = nRows - GetRowCount();
- // If we are about to lose rows, then we need to delete the GridCell objects
- // in each column within each row
- if (addedRows < 0)
- {
- if (!GetVirtualMode())
- {
- for (int row = nRows; row < m_nRows; row++)
- {
- // Delete cells
- for (int col = 0; col < m_nCols; col++)
- DestroyCell(row, col);
- // Delete rows
- GRID_ROW* pRow = m_RowData[row];
- if (pRow)
- delete pRow;
- }
- }
- m_nRows = nRows;
- }
- TRY
- {
- m_arRowHeights.SetSize(nRows);
- if (GetVirtualMode())
- {
- m_nRows = nRows;
- if (addedRows > 0)
- {
- int startRow = nRows - addedRows;
- for (int row = startRow; row < nRows; row++)
- m_arRowHeights[row] = m_cellDefault.GetHeight();
- }
- }
- else
- {
- // Change the number of rows.
- m_RowData.SetSize(nRows);
- // If we have just added rows, we need to construct new elements for each cell
- // and set the default row height
- if (addedRows > 0)
- {
- // initialize row heights and data
- int startRow = nRows - addedRows;
- for (int row = startRow; row < nRows; row++)
- {
- m_arRowHeights[row] = m_cellDefault.GetHeight();
- m_RowData[row] = new GRID_ROW;
- m_RowData[row]->SetSize(m_nCols);
- for (int col = 0; col < m_nCols; col++)
- {
- GRID_ROW* pRow = m_RowData[row];
- if (pRow && !GetVirtualMode())
- pRow->SetAt(col, CreateCell(row, col));
- }
- m_nRows++;
- }
- }
- }
- }
- CATCH(CMemoryException, e)
- {
- e->ReportError();
- bResult = FALSE;
- }
- END_CATCH
- SetModified();
- ResetScrollBars();
- Refresh();
- return bResult;
- }
- BOOL CGridCtrl::SetColumnCount(int nCols)
- {
- BOOL bResult = TRUE;
- ASSERT(nCols >= 0);
- if (nCols == GetColumnCount())
- return bResult;
- // Force recalculation
- m_idTopLeftCell.col = -1;
- if (nCols < m_nFixedCols)
- m_nFixedCols = nCols;
- if (m_idCurrentCell.col >= nCols)
- SetFocusCell(-1, -1);
- int addedCols = nCols - GetColumnCount();
- // If we are about to lose columns, then we need to delete the GridCell objects
- // within each column
- if (addedCols < 0 && !GetVirtualMode())
- {
- for (int row = 0; row < m_nRows; row++)
- for (int col = nCols; col < GetColumnCount(); col++)
- DestroyCell(row, col);
- }
- TRY
- {
- // Change the number of columns.
- m_arColWidths.SetSize(nCols);
- // Change the number of columns in each row.
- if (!GetVirtualMode())
- for (int i = 0; i < m_nRows; i++)
- if (m_RowData[i])
- m_RowData[i]->SetSize(nCols);
- // If we have just added columns, we need to construct new elements for each cell
- // and set the default column width
- if (addedCols > 0)
- {
- // initialized column widths
- int col = 0;
- int startCol = nCols - addedCols;
- for (col = startCol; col < nCols; col++)
- m_arColWidths[col] = m_cellFixedColDef.GetWidth();
- // initialise column data
- if (!GetVirtualMode())
- {
- for (int row = 0; row < m_nRows; row++)
- for (col = startCol; col < nCols; col++)
- {
- GRID_ROW* pRow = m_RowData[row];
- if (pRow)
- pRow->SetAt(col, CreateCell(row, col));
- }
- }
- }
- // else // check for selected cell ranges
- // ResetSelectedRange();
- }
- CATCH(CMemoryException, e)
- {
- e->ReportError();
- bResult = FALSE;
- }
- END_CATCH
- m_nCols = nCols;
- SetModified();
- ResetScrollBars();
- Refresh();
- return bResult;
- }
- // Insert a column at a given position, or add to end of columns (if nColumn = -1)
- int CGridCtrl::InsertColumn(LPCTSTR strHeading,
- UINT nFormat /* = DT_CENTER|DT_VCENTER|DT_SINGLELINE */,
- int nColumn /* = -1 */)
- {
- if (nColumn >= 0 && nColumn < m_nFixedCols)
- {
- // TODO: Fix it so column insertion works for in the fixed column area
- ASSERT(FALSE);
- return -1;
- }
- // If the insertion is for a specific column, check it's within range.
- if (nColumn >= 0 && nColumn > GetColumnCount())
- return -1;
- // Force recalculation
- m_idTopLeftCell.col = -1;
- ResetSelectedRange();
- // Gotta be able to at least _see_ some of the column.
- if (m_nRows < 1)
- SetRowCount(1);
- // Allow the user to insert after the last of the columns, but process it as a
- // "-1" column, meaning it gets flaged as being the last column, and not a regular
- // "insert" routine.
- if (nColumn == GetColumnCount())
- nColumn = -1;
- TRY
- {
- if (nColumn < 0)
- {
- nColumn = m_nCols;
- m_arColWidths.Add(0);
- if (!GetVirtualMode())
- {
- for (int row = 0; row < m_nRows; row++)
- {
- GRID_ROW* pRow = m_RowData[row];
- if (!pRow)
- return -1;
- pRow->Add(CreateCell(row, nColumn));
- }
- }
- }
- else
- {
- m_arColWidths.InsertAt(nColumn, (int)0, 1);
- if (!GetVirtualMode())
- {
- for (int row = 0; row < m_nRows; row++)
- {
- GRID_ROW* pRow = m_RowData[row];
- if (!pRow)
- return -1;
- pRow->InsertAt(nColumn, CreateCell(row, nColumn));
- }
- }
- }
- }
- CATCH(CMemoryException, e)
- {
- e->ReportError();
- return FALSE;
- }
- END_CATCH
- m_nCols++;
- // Initialise column data
- SetItemText(0, nColumn, strHeading);
- for (int row = 0; row < m_nRows; row++)
- SetItemFormat(row, nColumn, nFormat);
- // initialized column width
- m_arColWidths[nColumn] = GetTextExtent(0, nColumn, strHeading).cx;
- if (m_idCurrentCell.col != -1 && nColumn < m_idCurrentCell.col)
- m_idCurrentCell.col++;
- ResetScrollBars();
- SetModified();
- return nColumn;
- }
- // Insert a row at a given position, or add to end of rows (if nRow = -1)
- int CGridCtrl::InsertRow(LPCTSTR strHeading, int nRow /* = -1 */)
- {
- if (nRow >= 0 && nRow < m_nFixedRows)
- {
- // TODO: Fix it so column insertion works for in the fixed row area
- ASSERT(FALSE);
- return -1;
- }
- // If the insertion is for a specific row, check it's within range.
- if (nRow >= 0 && nRow >= GetRowCount())
- return -1;
- // Force recalculation
- m_idTopLeftCell.col = -1;
- ResetSelectedRange();
- // Gotta be able to at least _see_ some of the row.
- if (m_nCols < 1)
- SetColumnCount(1);
- TRY
- {
- // Adding a row to the bottom
- if (nRow < 0)
- {
- nRow = m_nRows;
- m_arRowHeights.Add(0);
- if (!GetVirtualMode())
- m_RowData.Add(new GRID_ROW);
- }
- else
- {
- m_arRowHeights.InsertAt(nRow, (int)0, 1);
- if (!GetVirtualMode())
- m_RowData.InsertAt(nRow, new GRID_ROW);
- }
- if (!GetVirtualMode())
- m_RowData[nRow]->SetSize(m_nCols);
- }
- CATCH(CMemoryException, e)
- {
- e->ReportError();
- return FALSE;
- }
- END_CATCH
- m_nRows++;
- // Initialise cell data
- if (!GetVirtualMode())
- {
- for (int col = 0; col < m_nCols; col++)
- {
- GRID_ROW* pRow = m_RowData[nRow];
- if (!pRow)
- return -1;
- pRow->SetAt(col, CreateCell(nRow, col));
- }
- }
- // Set row title
- SetItemText(nRow, 0, strHeading);
- // initialized row height
- if (strHeading && strHeading[0])
- m_arRowHeights[nRow] = GetTextExtent(nRow, 0, strHeading).cy;
- else
- m_arRowHeights[nRow] = m_cellFixedRowDef.GetHeight();
- if (m_idCurrentCell.row != -1 && nRow < m_idCurrentCell.row)
- m_idCurrentCell.row++;
- ResetScrollBars();
- SetModified();
- return nRow;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // Cell creation stuff
- BOOL CGridCtrl::SetCellType(int nRow, int nCol, CRuntimeClass* pRuntimeClass)
- {
- if (GetVirtualMode())
- return FALSE;
- ASSERT(IsValid(nRow, nCol));
- if (!IsValid(nRow, nCol))
- return FALSE;
- if (!pRuntimeClass->IsDerivedFrom(RUNTIME_CLASS(CGridCellBase)))
- {
- ASSERT(FALSE);
- return FALSE;
- }
- CGridCellBase* pNewCell = (CGridCellBase*)pRuntimeClass->CreateObject();
- CGridCellBase* pCurrCell = GetCell(nRow, nCol);
- if (pCurrCell)
- *pNewCell = *pCurrCell;
- SetCell(nRow, nCol, pNewCell);
- delete pCurrCell;
- return TRUE;
- }
- BOOL CGridCtrl::SetDefaultCellType(CRuntimeClass* pRuntimeClass)
- {
- ASSERT(pRuntimeClass != NULL);
- if (!pRuntimeClass->IsDerivedFrom(RUNTIME_CLASS(CGridCellBase)))
- {
- ASSERT(FALSE);
- return FALSE;
- }
- m_pRtcDefault = pRuntimeClass;
- return TRUE;
- }
- // Creates a new grid cell and performs any necessary initialisation
- /*virtual*/ CGridCellBase* CGridCtrl::CreateCell(int nRow, int nCol)
- {
- ASSERT(!GetVirtualMode());
- if (!m_pRtcDefault || !m_pRtcDefault->IsDerivedFrom(RUNTIME_CLASS(CGridCellBase)))
- {
- ASSERT(FALSE);
- return NULL;
- }
- CGridCellBase* pCell = (CGridCellBase*)m_pRtcDefault->CreateObject();
- if (!pCell)
- return NULL;
- pCell->SetGrid(this);
- pCell->SetCoords(nRow, nCol);
- if (nCol < m_nFixedCols)
- pCell->SetState(pCell->GetState() | GVIS_FIXED | GVIS_FIXEDCOL);
- if (nRow < m_nFixedRows)
- pCell->SetState(pCell->GetState() | GVIS_FIXED | GVIS_FIXEDROW);
- pCell->SetFormat(pCell->GetDefaultCell()->GetFormat());
- return pCell;
- }
- // Performs any cell cleanup necessary to maintain grid integrity
- /*virtual*/ void CGridCtrl::DestroyCell(int nRow, int nCol)
- {
- // Should NEVER get here in virtual mode.
- ASSERT(!GetVirtualMode());
- // Set the cells state to 0. If the cell is selected, this
- // will remove the cell from the selected list.
- SetItemState(nRow, nCol, 0);
- delete GetCell(nRow, nCol);
- }
- BOOL CGridCtrl::DeleteColumn(int nColumn)
- {
- if (nColumn < 0 || nColumn >= GetColumnCount())
- return FALSE;
- ResetSelectedRange();
- if (!GetVirtualMode())
- {
- for (int row = 0; row < GetRowCount(); row++)
- {
- GRID_ROW* pRow = m_RowData[row];
- if (!pRow)
- return FALSE;
- DestroyCell(row, nColumn);
- pRow->RemoveAt(nColumn);
- }
- }
- m_arColWidths.RemoveAt(nColumn);
- m_nCols--;
- if (nColumn < m_nFixedCols)
- m_nFixedCols--;
- if (nColumn == m_idCurrentCell.col)
- m_idCurrentCell.row = m_idCurrentCell.col = -1;
- else if (nColumn < m_idCurrentCell.col)
- m_idCurrentCell.col--;
- ResetScrollBars();
- SetModified();
- return TRUE;
- }
- BOOL CGridCtrl::DeleteRow(int nRow)
- {
- if (nRow < 0 || nRow >= GetRowCount())
- return FALSE;
- ResetSelectedRange();
- if (!GetVirtualMode())
- {
- GRID_ROW* pRow = m_RowData[nRow];
- if (!pRow)
- return FALSE;
- for (int col = 0; col < GetColumnCount(); col++)
- DestroyCell(nRow, col);
- delete pRow;
- m_RowData.RemoveAt(nRow);
- }
- m_arRowHeights.RemoveAt(nRow);
- m_nRows--;
- if (nRow < m_nFixedRows)
- m_nFixedRows--;
- if (nRow == m_idCurrentCell.row)
- m_idCurrentCell.row = m_idCurrentCell.col = -1;
- else if (nRow < m_idCurrentCell.row)
- m_idCurrentCell.row--;
- ResetScrollBars();
- SetModified();
- return TRUE;
- }
- // Handy function that removes all non-fixed rows
- BOOL CGridCtrl::DeleteNonFixedRows()
- {
- ResetSelectedRange();
- int nFixed = GetFixedRowCount();
- int nCount = GetRowCount();
- // Delete all data rows
- for (int nRow = nCount; nRow >= nFixed; nRow--)
- DeleteRow(nRow);
- return TRUE;
- }
- // Removes all rows, columns and data from the grid.
- BOOL CGridCtrl::DeleteAllItems()
- {
- ResetSelectedRange();
- m_arColWidths.RemoveAll();
- m_arRowHeights.RemoveAll();
- // Delete all cells in the grid
- if (!GetVirtualMode())
- {
- for (int row = 0; row < m_nRows; row++)
- {
- for (int col = 0; col < m_nCols; col++)
- DestroyCell(row, col);
- GRID_ROW* pRow = m_RowData[row];
- delete pRow;
- }
- // Remove all rows
- m_RowData.RemoveAll();
- }
- m_idCurrentCell.row = m_idCurrentCell.col = -1;
- m_nRows = m_nFixedRows = m_nCols = m_nFixedCols = 0;
- ResetScrollBars();
- SetModified();
- return TRUE;
- }
- void CGridCtrl::AutoFill()
- {
- if (!::IsWindow(m_hWnd))
- return;
- CRect rect;
- GetClientRect(rect);
- SetColumnCount(rect.Width() / m_cellDefault.GetWidth() + 1);
- SetRowCount(rect.Height() / m_cellDefault.GetHeight() + 1);
- SetFixedRowCount(1);
- SetFixedColumnCount(1);
- ExpandToFit();
- }
- /////////////////////////////////////////////////////////////////////////////
- // CGridCtrl data functions
- // Set CListCtrl::GetNextItem for details
- CCellID CGridCtrl::GetNextItem(CCellID& cell, int nFlags) const
- {
- if ((nFlags & GVNI_ALL) == GVNI_ALL)
- { // GVNI_ALL Search whole Grid beginning from cell
- // First row (cell.row) -- ONLY Columns to the right of cell
- // following rows -- ALL Columns
- int row = cell.row, col = cell.col + 1;
- if (row <= 0)
- row = GetFixedRowCount();
- for (; row < GetRowCount(); row++)
- {
- if (col <= 0)
- col = GetFixedColumnCount();
- for (; col < GetColumnCount(); col++)
- {
- int nState = GetItemState(row, col);
- if ((nFlags & GVNI_DROPHILITED && nState & GVIS_DROPHILITED) ||
- (nFlags & GVNI_FOCUSED && nState & GVIS_FOCUSED) ||
- (nFlags & GVNI_SELECTED && nState & GVIS_SELECTED) ||
- (nFlags & GVNI_READONLY && nState & GVIS_READONLY) ||
- (nFlags & GVNI_FIXED && nState & GVIS_FIXED) ||
- (nFlags & GVNI_MODIFIED && nState & GVIS_MODIFIED))
- return CCellID(row, col);
- }
- // go to First Column
- col = GetFixedColumnCount();
- }
- }
- else if ((nFlags & GVNI_BELOW) == GVNI_BELOW &&
- (nFlags & GVNI_TORIGHT) == GVNI_TORIGHT)
- { // GVNI_AREA Search Grid beginning from cell to Lower-Right of Grid
- // Only rows starting with cell.row and below
- // All rows -- ONLY Columns to the right of cell
- int row = cell.row;
- if (row <= 0)
- row = GetFixedRowCount();
- for (; row < GetRowCount(); row++)
- {
- int col = cell.col + 1;
- if (col <= 0)
- col = GetFixedColumnCount();
- for (; col < GetColumnCount(); col++)
- {
- int nState = GetItemState(row, col);
- if ((nFlags & GVNI_DROPHILITED && nState & GVIS_DROPHILITED) ||
- (nFlags & GVNI_FOCUSED && nState & GVIS_FOCUSED) ||
- (nFlags & GVNI_SELECTED && nState & GVIS_SELECTED) ||
- (nFlags & GVNI_READONLY && nState & GVIS_READONLY) ||
- (nFlags & GVNI_FIXED && nState & GVIS_FIXED) ||
- (nFlags & GVNI_MODIFIED && nState & GVIS_MODIFIED))
- return CCellID(row, col);
- }
- }
- }
- else if ((nFlags & GVNI_ABOVE) == GVNI_ABOVE)
- {
- for (int row = cell.row - 1; row >= GetFixedRowCount(); row--)
- {
- int nState = GetItemState(row, cell.col);
- if ((nFlags & GVNI_DROPHILITED && nState & GVIS_DROPHILITED) ||
- (nFlags & GVNI_FOCUSED && nState & GVIS_FOCUSED) ||
- (nFlags & GVNI_SELECTED && nState & GVIS_SELECTED) ||
- (nFlags & GVNI_READONLY && nState & GVIS_READONLY) ||
- (nFlags & GVNI_FIXED && nState & GVIS_FIXED) ||
- (nFlags & GVNI_MODIFIED && nState & GVIS_MODIFIED))
- return CCellID(row, cell.col);
- }
- }
- else if ((nFlags & GVNI_BELOW) == GVNI_BELOW)
- {
- for (int row = cell.row + 1; row < GetRowCount(); row++)
- {
- int nState = GetItemState(row, cell.col);
- if ((nFlags & GVNI_DROPHILITED && nState & GVIS_DROPHILITED) ||
- (nFlags & GVNI_FOCUSED && nState & GVIS_FOCUSED) ||
- (nFlags & GVNI_SELECTED && nState & GVIS_SELECTED) ||
- (nFlags & GVNI_READONLY && nState & GVIS_READONLY) ||
- (nFlags & GVNI_FIXED && nState & GVIS_FIXED) ||
- (nFlags & GVNI_MODIFIED && nState & GVIS_MODIFIED))
- return CCellID(row, cell.col);
- }
- }
- else if ((nFlags & GVNI_TOLEFT) == GVNI_TOLEFT)
- {
- for (int col = cell.col - 1; col >= GetFixedColumnCount(); col--)
- {
- int nState = GetItemState(cell.row, col);
- if ((nFlags & GVNI_DROPHILITED && nState & GVIS_DROPHILITED) ||
- (nFlags & GVNI_FOCUSED && nState & GVIS_FOCUSED) ||
- (nFlags & GVNI_SELECTED && nState & GVIS_SELECTED) ||
- (nFlags & GVNI_READONLY && nState & GVIS_READONLY) ||
- (nFlags & GVNI_FIXED && nState & GVIS_FIXED) ||
- (nFlags & GVNI_MODIFIED && nState & GVIS_MODIFIED))
- return CCellID(cell.row, col);
- }
- }
- else if ((nFlags & GVNI_TORIGHT) == GVNI_TORIGHT)
- {
- for (int col = cell.col + 1; col < GetColumnCount(); col++)
- {
- int nState = GetItemState(cell.row, col);
- if ((nFlags & GVNI_DROPHILITED && nState & GVIS_DROPHILITED) ||
- (nFlags & GVNI_FOCUSED && nState & GVIS_FOCUSED) ||
- (nFlags & GVNI_SELECTED && nState & GVIS_SELECTED) ||
- (nFlags & GVNI_READONLY && nState & GVIS_READONLY) ||
- (nFlags & GVNI_FIXED && nState & GVIS_FIXED) ||
- (nFlags & GVNI_MODIFIED && nState & GVIS_MODIFIED))
- return CCellID(cell.row, col);
- }
- }
- return CCellID(-1, -1);
- }
- // Sorts on a given column using the cell text
- BOOL CGridCtrl::SortTextItems(int nCol, BOOL bAscending, LPARAM data /* = 0 */)
- {
- SetSortColumn(nCol);
- SetSortAscending(bAscending);
- ResetSelectedRange();
- SetFocusCell(-1, -1);
- // -AfxMessageBox("SortTextItems");
- return CGridCtrl::SortItems(pfnCellTextCompare, nCol, bAscending, data);
- }
- void CGridCtrl::SetCompareFunction(PFNLVCOMPARE pfnCompare)
- {
- m_pfnCompare = pfnCompare;
- }
- // Sorts on a given column using the cell text and using the specified comparison
- // function
- BOOL CGridCtrl::SortItems(int nCol, BOOL bAscending, LPARAM data /* = 0 */)
- {
- SetSortColumn(nCol);
- SetSortAscending(bAscending);
- ResetSelectedRange();
- SetFocusCell(-1, -1);
- if (m_pfnCompare == NULL)
- return CGridCtrl::SortItems(pfnCellTextCompare, nCol, bAscending, data);
- else
- return CGridCtrl::SortItems(m_pfnCompare, nCol, bAscending, data);
- }
- // Sorts on a given column using the supplied compare function (see CListCtrl::SortItems)
- BOOL CGridCtrl::SortItems(PFNLVCOMPARE pfnCompare, int nCol, BOOL bAscending,
- LPARAM data /* = 0 */)
- {
- SetSortColumn(nCol);
- SetSortAscending(bAscending);
- ResetSelectedRange();
- SetFocusCell(-1, -1);
- return SortItems(pfnCompare, nCol, bAscending, data, GetFixedRowCount(), -1);
- }
- int CALLBACK CGridCtrl::pfnCellTextCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
- {
- UNUSED_ALWAYS(lParamSort);
- CGridCellBase* pCell1 = (CGridCellBase*)lParam1;
- CGridCellBase* pCell2 = (CGridCellBase*)lParam2;
- if (!pCell1 || !pCell2) return 0;
- return _tcscmp(pCell1->GetText(), pCell2->GetText());
- }
- int CALLBACK CGridCtrl::pfnCellNumericCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
- {
- UNUSED_ALWAYS(lParamSort);
- CGridCellBase* pCell1 = (CGridCellBase*)lParam1;
- CGridCellBase* pCell2 = (CGridCellBase*)lParam2;
- if (!pCell1 || !pCell2) return 0;
- int nValue1 = _ttol(pCell1->GetText());
- int nValue2 = _ttol(pCell2->GetText());
- if (nValue1 < nValue2)
- return -1;
- else if (nValue1 == nValue2)
- return 0;
- else
- return 1;
- }
- // private recursive sort implementation
- BOOL CGridCtrl::SortItems(PFNLVCOMPARE pfnCompare, int nCol, BOOL bAscending, LPARAM data,
- int low, int high)
- {
- ///-AfxMessageBox("SortItems3");
- if (nCol >= GetColumnCount())
- return FALSE;
- if (high == -1)
- high = GetRowCount() - 1;
- int lo = low;
- int hi = high;
- if (hi <= lo)
- return FALSE;
- //LPARAM midItem = GetItemData((lo + hi)/2, nCol);
- LPARAM pMidCell = (LPARAM)GetCell((lo + hi) / 2, nCol);
- // loop through the list until indices cross
- while (lo <= hi)
- {
- // Find the first element that is greater than or equal to the partition
- // element starting from the left Index.
- if (bAscending)
- while (lo < high && pfnCompare((LPARAM)GetCell(lo, nCol), (LPARAM)pMidCell, data) < 0)
- ++lo;
- else
- while (lo < high && pfnCompare((LPARAM)GetCell(lo, nCol), pMidCell, data) > 0)
- ++lo;
- // Find an element that is smaller than or equal to the partition
- // element starting from the right Index.
- if (bAscending)
- while (hi > low && pfnCompare((LPARAM)GetCell(hi, nCol), pMidCell, data) > 0)
- --hi;
- else
- while (hi > low && pfnCompare((LPARAM)GetCell(hi, nCol), pMidCell, data) < 0)
- --hi;
- // If the indexes have not crossed, swap if the items are not equal
- if (lo <= hi)
- {
- // swap only if the items are not equal
- if (pfnCompare((LPARAM)GetCell(lo, nCol), (LPARAM)GetCell(hi, nCol), data) != 0)
- {
- for (int col = 0; col < GetColumnCount(); col++)
- {
- CGridCellBase *pCell = GetCell(lo, col);
- SetCell(lo, col, GetCell(hi, col));
- SetCell(hi, col, pCell);
- }
- UINT nRowHeight = m_arRowHeights[lo];
- m_arRowHeights[lo] = m_arRowHeights[hi];
- m_arRowHeights[hi] = nRowHeight;
- }
- ++lo;
- --hi;
- }
- }
- // If the right index has not reached the left side of array
- // must now sort the left partition.
- if (low < hi)
- SortItems(pfnCompare, nCol, bAscending, data, low, hi);
- // If the left index has not reached the right side of array
- // must now sort the right partition.
- if (lo < high)
- SortItems(pfnCompare, nCol, bAscending, data, lo, high);
- return TRUE;
- }
- /////////////////////////////////////////////////////////////////////////////
- // CGridCtrl data functions
- BOOL CGridCtrl::SetItem(const GV_ITEM* pItem)
- {
- if (!pItem || GetVirtualMode())
- return FALSE;
- CGridCellBase* pCell = GetCell(pItem->row, pItem->col);
- if (!pCell)
- return FALSE;
- SetModified(TRUE, pItem->row, pItem->col);
- if (pItem->mask & GVIF_TEXT)
- pCell->SetText(pItem->strText);
- if (pItem->mask & GVIF_PARAM)
- pCell->SetData(pItem->lParam);
- if (pItem->mask & GVIF_IMAGE)
- pCell->SetImage(pItem->iImage);
- if (pItem->mask & GVIF_STATE)
- SetItemState(pItem->row, pItem->col, pItem->nState);
- if (pItem->mask & GVIF_FORMAT)
- pCell->SetFormat(pItem->nFormat);
- if (pItem->mask & GVIF_BKCLR)
- pCell->SetBackClr(pItem->crBkClr);
- if (pItem->mask & GVIF_FGCLR)
- pCell->SetTextClr(pItem->crFgClr);
- if (pItem->mask & GVIF_FONT)
- pCell->SetFont(&(pItem->lfFont));
- if (pItem->mask & GVIF_MARGIN)
- pCell->SetMargin(pItem->nMargin);
- return TRUE;
- }
- BOOL CGridCtrl::GetItem(GV_ITEM* pItem)
- {
- if (!pItem)
- return FALSE;
- CGridCellBase* pCell = GetCell(pItem->row, pItem->col);
- if (!pCell)
- return FALSE;
- if (pItem->mask & GVIF_TEXT)
- pItem->strText = GetItemText(pItem->row, pItem->col);
- if (pItem->mask & GVIF_PARAM)
- pItem->lParam = pCell->GetData();;
- if (pItem->mask & GVIF_IMAGE)
- pItem->iImage = pCell->GetImage();
- if (pItem->mask & GVIF_STATE)
- pItem->nState = pCell->GetState();
- if (pItem->mask & GVIF_FORMAT)
- pItem->nFormat = pCell->GetFormat();
- if (pItem->mask & GVIF_BKCLR)
- pItem->crBkClr = pCell->GetBackClr();
- if (pItem->mask & GVIF_FGCLR)
- pItem->crFgClr = pCell->GetTextClr();
- if (pItem->mask & GVIF_FONT)
- memcpy(&(pItem->lfFont), pCell->GetFont(), sizeof(LOGFONT));
- if (pItem->mask & GVIF_MARGIN)
- pItem->nMargin = pCell->GetMargin();
- return TRUE;
- }
- BOOL CGridCtrl::SetItemText(int nRow, int nCol, LPCTSTR str)
- {
- if (GetVirtualMode())
- return FALSE;
- CGridCellBase* pCell = GetCell(nRow, nCol);
- if (!pCell)
- return FALSE;
- pCell->SetText(str);
- SetModified(TRUE, nRow, nCol);
- return TRUE;
- }
- #if !defined(_WIN32_WCE) || (_WIN32_WCE >= 210)
- // EFW - 06/13/99 - Added to support printf-style formatting codes
- BOOL CGridCtrl::SetItemTextFmt(int nRow, int nCol, LPCTSTR szFmt, ...)
- {
- if (GetVirtualMode())
- return FALSE;
- CString strText;
- va_list argptr;
- CGridCellBase* pCell = GetCell(nRow, nCol);
- if (!pCell)
- return FALSE;
- // Format the message text
- va_start(argptr, szFmt);
- strText.FormatV(szFmt, argptr);
- va_end(argptr);
- pCell->SetText(strText);
- SetModified(TRUE, nRow, nCol);
- return TRUE;
- }
- // EFW - 06/13/99 - Added to support string resource ID. Supports
- // a variable argument list too.
- BOOL CGridCtrl::SetItemTextFmtID(int nRow, int nCol, UINT nID, ...)
- {
- if (GetVirtualMode())
- return FALSE;
- CString strFmt, strText;
- va_list argptr;
- CGridCellBase* pCell = GetCell(nRow, nCol);
- if (!pCell)
- return FALSE;
- // Format the message text
- va_start(argptr, nID);
- VERIFY(strFmt.LoadString(nID));
- strText.FormatV(strFmt, argptr);
- va_end(argptr);
- pCell->SetText(strText);
- SetModified(TRUE, nRow, nCol);
- return TRUE;
- }
- #endif
- BOOL CGridCtrl::SetItemData(int nRow, int nCol, LPARAM lParam)
- {
- if (GetVirtualMode())
- return FALSE;
- CGridCellBase* pCell = GetCell(nRow, nCol);
- if (!pCell)
- return FALSE;
- pCell->SetData(lParam);
- SetModified(TRUE, nRow, nCol);
- return TRUE;
- }
- LPARAM CGridCtrl::GetItemData(int nRow, int nCol) const
- {
- CGridCellBase* pCell = GetCell(nRow, nCol);
- if (!pCell)
- return (LPARAM)0;
- return pCell->GetData();
- }
- BOOL CGridCtrl::SetItemImage(int nRow, int nCol, int iImage)
- {
- if (GetVirtualMode())
- return FALSE;
- CGridCellBase* pCell = GetCell(nRow, nCol);
- if (!pCell)
- return FALSE;
- pCell->SetImage(iImage);
- SetModified(TRUE, nRow, nCol);
- return TRUE;
- }
- int CGridCtrl::GetItemImage(int nRow, int nCol) const
- {
- CGridCellBase* pCell = GetCell(nRow, nCol);
- ASSERT(pCell);
- if (!pCell)
- return -1;
- return pCell->GetImage();
- }
- BOOL CGridCtrl::SetItemState(int nRow, int nCol, UINT state)
- {
- BOOL bSelected = IsCellSelected(nRow, nCol);
- // If the cell is being unselected, remove it from the selected list
- if (bSelected && !(state & GVIS_SELECTED))
- {
- CCellID cell;
- DWORD key = MAKELONG(nRow, nCol);
- if (m_SelectedCellMap.Lookup(key, (CCellID&)cell))
- {
- m_SelectedCellMap.RemoveKey(key);
- //chn add
- for (int i = 0; i < m_nArrayListChoose.GetCount(); i++)
- {
- if (m_nArrayListChoose.GetAt(i) == nRow)
- {
- m_nArrayListChoose.RemoveAt(i);
- break;
- }
- }
- }
- }
- // If cell is being selected, add it to the list of selected cells
- else if (!bSelected && (state & GVIS_SELECTED))
- {
- CCellID cell(nRow, nCol);
- m_SelectedCellMap.SetAt(MAKELONG(nRow, nCol), cell);
- //chn add
- bool bExist = false;
- for (int i = 0; i < m_nArrayListChoose.GetCount(); i++)
- {
- if (m_nArrayListChoose.GetAt(i) == nRow)
- {
- bExist = true;
- break;
- }
- }
- if (!bExist)
- m_nArrayListChoose.Add(nRow);
- }
- if (GetVirtualMode())
- return FALSE;
- CGridCellBase* pCell = GetCell(nRow, nCol);
- ASSERT(pCell);
- if (!pCell)
- return FALSE;
- // Set the cell's state
- pCell->SetState(state);
- return TRUE;
- }
- UINT CGridCtrl::GetItemState(int nRow, int nCol) const
- {
- CGridCellBase* pCell = GetCell(nRow, nCol);
- ASSERT(pCell);
- if (!pCell)
- return 0;
- return pCell->GetState();
- }
- BOOL CGridCtrl::SetItemFormat(int nRow, int nCol, UINT nFormat)
- {
- if (GetVirtualMode())
- return FALSE;
- CGridCellBase* pCell = GetCell(nRow, nCol);
- ASSERT(pCell);
- if (!pCell)
- return FALSE;
- pCell->SetFormat(nFormat);
- return TRUE;
- }
- UINT CGridCtrl::GetItemFormat(int nRow, int nCol) const
- {
- CGridCellBase* pCell = GetCell(nRow, nCol);
- ASSERT(pCell);
- if (!pCell)
- return 0;
- return pCell->GetFormat();
- }
- BOOL CGridCtrl::SetItemBkColour(int nRow, int nCol, COLORREF cr /* = CLR_DEFAULT */)
- {
- if (GetVirtualMode())
- return FALSE;
- CGridCellBase* pCell = GetCell(nRow, nCol);
- ASSERT(pCell);
- if (!pCell)
- return FALSE;
- pCell->SetBackClr(cr);
- return TRUE;
- }
- COLORREF CGridCtrl::GetItemBkColour(int nRow, int nCol) const
- {
- CGridCellBase* pCell = GetCell(nRow, nCol);
- ASSERT(pCell);
- if (!pCell)
- return 0;
- return pCell->GetBackClr();
- }
- BOOL CGridCtrl::SetItemFgColour(int nRow, int nCol, COLORREF cr /* = CLR_DEFAULT */)
- {
- if (GetVirtualMode())
- return FALSE;
- CGridCellBase* pCell = GetCell(nRow, nCol);
- ASSERT(pCell);
- if (!pCell)
- return FALSE;
- pCell->SetTextClr(cr);
- return TRUE;
- }
- COLORREF CGridCtrl::GetItemFgColour(int nRow, int nCol) const
- {
- CGridCellBase* pCell = GetCell(nRow, nCol);
- ASSERT(pCell);
- if (!pCell)
- return 0;
- return pCell->GetTextClr();
- }
- BOOL CGridCtrl::SetItemFont(int nRow, int nCol, const LOGFONT* plf)
- {
- if (GetVirtualMode())
- return FALSE;
- CGridCellBase* pCell = GetCell(nRow, nCol);
- ASSERT(pCell);
- if (!pCell)
- return FALSE;
- pCell->SetFont(plf);
- return TRUE;
- }
- const LOGFONT* CGridCtrl::GetItemFont(int nRow, int nCol)
- {
- CGridCellBase* pCell = GetCell(nRow, nCol);
- ASSERT(pCell);
- if (!pCell)
- return GetDefaultCell(nRow < GetFixedRowCount(), nCol < GetFixedColumnCount())->GetFont();
- return pCell->GetFont();
- }
- BOOL CGridCtrl::IsItemEditing(int nRow, int nCol)
- {
- CGridCellBase* pCell = GetCell(nRow, nCol);
- ASSERT(pCell);
- if (!pCell)
- return FALSE;
- return pCell->IsEditing();
- }
- ////////////////////////////////////////////////////////////////////////////////////
- // Row/Column size functions
- long CGridCtrl::GetVirtualWidth() const
- {
- long lVirtualWidth = 0;
- int iColCount = GetColumnCount();
- for (int i = 0; i < iColCount; i++)
- lVirtualWidth += m_arColWidths[i];
- return lVirtualWidth;
- }
- long CGridCtrl::GetVirtualHeight() const
- {
- long lVirtualHeight = 0;
- int iRowCount = GetRowCount();
- for (int i = 0; i < iRowCount; i++)
- lVirtualHeight += m_arRowHeights[i];
- return lVirtualHeight;
- }
- int CGridCtrl::GetRowHeight(int nRow) const
- {
- ASSERT(nRow >= 0 && nRow < m_nRows);
- if (nRow < 0 || nRow >= m_nRows)
- return -1;
- return m_arRowHeights[nRow];
- }
- int CGridCtrl::GetColumnWidth(int nCol) const
- {
- ASSERT(nCol >= 0 && nCol < m_nCols);
- if (nCol < 0 || nCol >= m_nCols)
- return -1;
- return m_arColWidths[nCol];
- }
- BOOL CGridCtrl::SetRowHeight(int nRow, int height)
- {
- ASSERT(nRow >= 0 && nRow < m_nRows && height >= 0);
- if (nRow < 0 || nRow >= m_nRows || height < 0)
- return FALSE;
- m_arRowHeights[nRow] = height;
- ResetScrollBars();
- return TRUE;
- }
- BOOL CGridCtrl::SetColumnWidth(int nCol, int width)
- {
- ASSERT(nCol >= 0 && nCol < m_nCols && width >= 0);
- if (nCol < 0 || nCol >= m_nCols || width < 0)
- return FALSE;
- m_arColWidths[nCol] = width;
- ResetScrollBars();
- return TRUE;
- }
- int CGridCtrl::GetFixedRowHeight() const
- {
- int nHeight = 0;
- for (int i = 0; i < m_nFixedRows; i++)
- nHeight += GetRowHeight(i);
- return nHeight;
- }
- int CGridCtrl::GetFixedColumnWidth() const
- {
- int nWidth = 0;
- for (int i = 0; i < m_nFixedCols; i++)
- nWidth += GetColumnWidth(i);
- return nWidth;
- }
- BOOL CGridCtrl::AutoSizeColumn(int nCol, UINT nAutoSizeStyle /*=GVS_DEFAULT*/,
- BOOL bResetScroll /*=TRUE*/)
- {
- ASSERT(nCol >= 0 && nCol < m_nCols);
- if (nCol < 0 || nCol >= m_nCols)
- return FALSE;
- // Skip hidden columns when autosizing
- if (GetColumnWidth(nCol) <= 0)
- return FALSE;
- CSize size;
- CDC* pDC = GetDC();
- if (!pDC)
- return FALSE;
- int nWidth = 0;
- ASSERT(GVS_DEFAULT <= nAutoSizeStyle && nAutoSizeStyle <= GVS_BOTH);
- if (nAutoSizeStyle == GVS_DEFAULT)
- nAutoSizeStyle = GetAutoSizeStyle();
- int nStartRow = (nAutoSizeStyle & GVS_HEADER) ? 0 : GetFixedRowCount();
- int nEndRow = (nAutoSizeStyle & GVS_DATA) ? GetRowCount() - 1 : GetFixedRowCount() - 1;
- if (GetVirtualMode())
- SendCacheHintToParent(CCellRange(nStartRow, nCol, nEndRow, nCol));
- for (int nRow = nStartRow; nRow <= nEndRow; nRow++)
- {
- CGridCellBase* pCell = GetCell(nRow, nCol);
- if (pCell)
- size = pCell->GetCellExtent(pDC);
- if (size.cx > nWidth)
- nWidth = size.cx;
- }
- if (GetVirtualMode())
- SendCacheHintToParent(CCellRange(-1, -1, -1, -1));
- m_arColWidths[nCol] = nWidth;
- ReleaseDC(pDC);
- if (bResetScroll)
- ResetScrollBars();
- return TRUE;
- }
- BOOL CGridCtrl::AutoSizeRow(int nRow, BOOL bResetScroll /*=TRUE*/)
- {
- ASSERT(nRow >= 0 && nRow < m_nRows);
- if (nRow < 0 || nRow >= m_nRows)
- return FALSE;
- // Skip hidden rows when autosizing
- if (GetRowHeight(nRow) <= 0)
- return FALSE;
- CSize size;
- CDC* pDC = GetDC();
- if (!pDC)
- return FALSE;
- int nHeight = 0;
- int nNumColumns = GetColumnCount();
- if (GetVirtualMode())
- SendCacheHintToParent(CCellRange(nRow, 0, nRow, nNumColumns));
- for (int nCol = 0; nCol < nNumColumns; nCol++)
- {
- CGridCellBase* pCell = GetCell(nRow, nCol);
- if (pCell)
- size = pCell->GetCellExtent(pDC);
- if (size.cy > nHeight)
- nHeight = size.cy;
- }
- m_arRowHeights[nRow] = nHeight;
- if (GetVirtualMode())
- SendCacheHintToParent(CCellRange(-1, -1, -1, -1));
- ReleaseDC(pDC);
- if (bResetScroll)
- ResetScrollBars();
- return TRUE;
- }
- void CGridCtrl::AutoSizeColumns(UINT nAutoSizeStyle /*=GVS_DEFAULT*/)
- {
- int nNumColumns = GetColumnCount();
- for (int nCol = 0; nCol < nNumColumns; nCol++)
- {
- // Skip hidden columns when autosizing
- if (GetColumnWidth(nCol) > 0)
- AutoSizeColumn(nCol, nAutoSizeStyle, FALSE);
- }
- ResetScrollBars();
- }
- void CGridCtrl::AutoSizeRows()
- {
- int nNumRows = GetRowCount();
- for (int nRow = 0; nRow < nNumRows; nRow++)
- {
- // Skip hidden rows when autosizing
- if (GetRowHeight(nRow) > 0)
- AutoSizeRow(nRow, FALSE);
- }
- ResetScrollBars();
- }
- // sizes all rows and columns
- // faster than calling both AutoSizeColumns() and AutoSizeRows()
- void CGridCtrl::AutoSize(UINT nAutoSizeStyle /*=GVS_DEFAULT*/)
- {
- CDC* pDC = GetDC();
- if (!pDC)
- return;
- int nNumColumns = GetColumnCount();
- int nCol, nRow;
- ASSERT(GVS_DEFAULT <= nAutoSizeStyle && nAutoSizeStyle <= GVS_BOTH);
- if (nAutoSizeStyle == GVS_DEFAULT)
- nAutoSizeStyle = GetAutoSizeStyle();
- int nStartRow = (nAutoSizeStyle & GVS_HEADER) ? 0 : GetFixedRowCount();
- int nEndRow = (nAutoSizeStyle & GVS_DATA) ? GetRowCount() - 1 : GetFixedRowCount() - 1;
- if (GetVirtualMode())
- SendCacheHintToParent(CCellRange(nStartRow, 0, nEndRow, nNumColumns));
- // Row initialisation - only work on rows whose height is > 0
- for (nRow = nStartRow; nRow <= nEndRow; nRow++)
- {
- if (GetRowHeight(nRow) > 0)
- m_arRowHeights[nRow] = 1;
- }
- CSize size;
- for (nCol = 0; nCol < nNumColumns; nCol++)
- {
- // Don't size hidden columns or rows
- if (GetColumnWidth(nCol) > 0)
- {
- // Skip columns that are hidden, but now initialize
- m_arColWidths[nCol] = 0;
- for (nRow = nStartRow; nRow <= nEndRow; nRow++)
- {
- if (GetRowHeight(nRow) > 0)
- {
- CGridCellBase* pCell = GetCell(nRow, nCol);
- if (pCell)
- size = pCell->GetCellExtent(pDC);
- if (size.cx > (int)m_arColWidths[nCol])
- m_arColWidths[nCol] = size.cx;
- if (size.cy > (int)m_arRowHeights[nRow])
- m_arRowHeights[nRow] = size.cy;
- }
- }
- }
- }
- if (GetVirtualMode())
- SendCacheHintToParent(CCellRange(-1, -1, -1, -1));
- ReleaseDC(pDC);
- ResetScrollBars();
- Refresh();
- }
- // Expands the columns to fit the screen space. If bExpandFixed is FALSE then fixed
- // columns will not be affected
- void CGridCtrl::ExpandColumnsToFit(BOOL bExpandFixed /*=TRUE*/)
- {
- if (bExpandFixed)
- {
- if (GetColumnCount() <= 0) return;
- }
- else
- {
- if (GetColumnCount() <= GetFixedColumnCount()) return;
- }
- EnableScrollBars(SB_HORZ, FALSE);
- CRect rect;
- GetClientRect(rect);
- int nFirstColumn = (bExpandFixed) ? 0 : GetFixedColumnCount();
- int col = 0;
- int nNumColumnsAffected = 0;
- for (col = nFirstColumn; col < GetColumnCount(); col++)
- {
- if (m_arColWidths[col] > 0)
- nNumColumnsAffected++;
- }
- if (nNumColumnsAffected <= 0)
- return;
- long virtualWidth = GetVirtualWidth();
- int nDifference = rect.Width() - (int)virtualWidth;
- int nColumnAdjustment = nDifference / nNumColumnsAffected;
- for (col = nFirstColumn; col < GetColumnCount(); col++)
- {
- if (m_arColWidths[col] > 0)
- m_arColWidths[col] += nColumnAdjustment;
- }
- if (nDifference > 0)
- {
- int leftOver = nDifference % nNumColumnsAffected;
- for (int nCount = 0, col = nFirstColumn;
- (col < GetColumnCount()) && (nCount < leftOver); col++, nCount++)
- {
- if (m_arColWidths[col] > 0)
- m_arColWidths[col] += 1;
- }
- }
- else
- {
- int leftOver = (-nDifference) % nNumColumnsAffected;
- for (int nCount = 0, col = nFirstColumn;
- (col < GetColumnCount()) && (nCount < leftOver); col++, nCount++)
- {
- if (m_arColWidths[col] > 0)
- m_arColWidths[col] -= 1;
- }
- }
- Refresh();
- ResetScrollBars();
- }
- void CGridCtrl::ExpandLastColumn()
- {
- if (GetColumnCount() <= 0)
- return;
- // Search for last non-hidden column
- int nLastColumn = GetColumnCount() - 1;
- while (m_arColWidths[nLastColumn] <= 0)
- nLastColumn--;
- if (nLastColumn <= 0)
- return;
- EnableScrollBars(SB_HORZ, FALSE);
- CRect rect;
- GetClientRect(rect);
- long virtualWidth = GetVirtualWidth();
- int nDifference = rect.Width() - (int)virtualWidth;
- if (nDifference > 0)
- {
- //if (GetVirtualHeight() > rect.Height())
- // nDifference -= GetSystemMetrics(SM_CXVSCROLL);
- m_arColWidths[nLastColumn] += nDifference;
- Refresh();
- }
- ResetScrollBars();
- }
- // Expands the rows to fit the screen space. If bExpandFixed is FALSE then fixed
- // rows will not be affected
- void CGridCtrl::ExpandRowsToFit(BOOL bExpandFixed /*=TRUE*/)
- {
- if (bExpandFixed)
- {
- if (GetRowCount() <= 0) return;
- }
- else
- {
- if (GetRowCount() <= GetFixedRowCount()) return;
- }
- EnableScrollBars(SB_VERT, FALSE);
- CRect rect;
- GetClientRect(rect);
- int nFirstRow = (bExpandFixed) ? 0 : GetFixedRowCount();
- int row = 0;
- int nNumRowsAffected = 0;
- for (row = nFirstRow; row < GetRowCount(); row++)
- {
- if (m_arRowHeights[row] > 0)
- nNumRowsAffected++;
- }
- if (nNumRowsAffected <= 0)
- return;
- long virtualHeight = GetVirtualHeight();
- int nDifference = rect.Height() - (int)virtualHeight;
- int nRowAdjustment = nDifference / nNumRowsAffected;
- for (row = nFirstRow; row < GetRowCount(); row++)
- {
- if (m_arRowHeights[row] > 0)
- m_arRowHeights[row] += nRowAdjustment;
- }
- if (nDifference > 0)
- {
- int leftOver = nDifference % nNumRowsAffected;
- for (int nCount = 0, row = nFirstRow;
- (row < GetRowCount()) && (nCount < leftOver); row++, nCount++)
- {
- if (m_arRowHeights[row] > 0)
- m_arRowHeights[row] += 1;
- }
- }
- else
- {
- int leftOver = (-nDifference) % nNumRowsAffected;
- for (int nCount = 0, row = nFirstRow;
- (row < GetRowCount()) && (nCount < leftOver); row++, nCount++)
- {
- if (m_arRowHeights[row] > 0)
- m_arRowHeights[row] -= 1;
- }
- }
- Refresh();
- ResetScrollBars();
- }
- // Expands the cells to fit the screen space. If bExpandFixed is FALSE then fixed
- // cells will not be affected
- void CGridCtrl::ExpandToFit(BOOL bExpandFixed /*=TRUE*/)
- {
- ExpandColumnsToFit(bExpandFixed); // This will remove any existing horz scrollbar
- ExpandRowsToFit(bExpandFixed); // This will remove any existing vert scrollbar
- ExpandColumnsToFit(bExpandFixed); // Just in case the first adjustment was with a vert
- // scrollbar in place
- Refresh();
- }
- /////////////////////////////////////////////////////////////////////////////////////
- // Attributes
- void CGridCtrl::SetVirtualMode(BOOL bVirtual)
- {
- DeleteAllItems();
- m_bVirtualMode = bVirtual;
- // Force some defaults here.
- if (m_bVirtualMode)
- {
- SetEditable(FALSE);
- SetHeaderSort(FALSE);
- SetAutoSizeStyle(GVS_HEADER);
- SetFixedColumnSelection(FALSE);
- SetFixedRowSelection(FALSE);
- }
- }
- void CGridCtrl::SetGridLines(int nWhichLines /*=GVL_BOTH*/)
- {
- m_nGridLines = nWhichLines;
- Refresh();
- }
- void CGridCtrl::SetListMode(BOOL bEnableListMode /*=TRUE*/)
- {
- ResetSelectedRange();
- SetSortColumn(-1);
- m_bListMode = bEnableListMode;
- SetFixedRowSelection(FALSE);
- Refresh();
- }
- void CGridCtrl::SetSortColumn(int nCol)
- {
- if (m_nSortColumn >= 0)
- InvalidateCellRect(0, m_nSortColumn);
- m_nSortColumn = nCol;
- if (nCol >= 0)
- InvalidateCellRect(0, nCol);
- }
- BOOL CGridCtrl::IsCellFixed(int nRow, int nCol)
- {
- return (nRow < GetFixedRowCount() || nCol < GetFixedColumnCount());
- }
- void CGridCtrl::SetModified(BOOL bModified /*=TRUE*/, int nRow /*=-1*/, int nCol /*=-1*/)
- {
- // Cannot guarantee sorting anymore...
- if (nCol < 0 || nCol == GetSortColumn())
- SetSortColumn(-1);
- if (nRow >= 0 && nCol >= 0)
- {
- if (bModified)
- {
- SetItemState(nRow, nCol, GetItemState(nRow, nCol) | GVIS_MODIFIED);
- m_bModified = TRUE;
- }
- else
- SetItemState(nRow, nCol, GetItemState(nRow, nCol) & ~GVIS_MODIFIED);
- }
- else
- m_bModified = bModified;
- if (!m_bModified)
- {
- for (int row = 0; row < GetRowCount(); row++)
- for (int col = 0; col < GetColumnCount(); col++)
- SetItemState(row, col, GetItemState(row, col) & ~GVIS_MODIFIED);
- }
- }
- BOOL CGridCtrl::GetModified(int nRow /*=-1*/, int nCol /*=-1*/)
- {
- if (nRow >= 0 && nCol >= 0)
- return ((GetItemState(nRow, nCol) & GVIS_MODIFIED) == GVIS_MODIFIED);
- else
- return m_bModified;
- }
- /////////////////////////////////////////////////////////////////////////////////////
- // GridCtrl cell visibility tests and invalidation/redraw functions
- void CGridCtrl::Refresh()
- {
- if (GetSafeHwnd() && m_bAllowDraw)
- Invalidate();
- }
- // EnsureVisible supplied by Roelf Werkman
- void CGridCtrl::EnsureVisible(int nRow, int nCol)
- {
- if (!m_bAllowDraw)
- return;
- CRect rectWindow;
- /*
- // set the scroll to the approximate position of row (Nigel Page-Jones)
- int nPos = (int)((float)nRow / GetRowCount() * 1000);
- float fPos = (float)nPos / 1000;
- SCROLLINFO scrollInfo;
- GetScrollInfo(SB_VERT, &scrollInfo);
- scrollInfo.nPos = (int)(scrollInfo.nMax * fPos);
- SetScrollInfo(SB_VERT, &scrollInfo, FALSE);
- GetClientRect(rectWindow);
- // redraw cells if necessary (Nigel Page-Jones)
- CCellID idTopLeft = GetTopleftNonFixedCell(FALSE);
- CCellID idNewTopLeft = GetTopleftNonFixedCell(TRUE);
- if (idNewTopLeft != idTopLeft)
- {
- rectWindow.top = GetFixedRowHeight();
- InvalidateRect(rectWindow);
- }
- */
- // We are gonna send some scroll messages, which will steal the focus
- // from it's rightful owner. Squirrel it away ourselves so we can give
- // it back. (Damir)
- CWnd* pFocusWnd = GetFocus();
- CCellRange VisibleCells = GetVisibleNonFixedCellRange();
- int right = nCol - VisibleCells.GetMaxCol();
- int left = VisibleCells.GetMinCol() - nCol;
- int down = nRow - VisibleCells.GetMaxRow();
- int up = VisibleCells.GetMinRow() - nRow;
- int iColumnStart;
- int iRowStart;
- iColumnStart = VisibleCells.GetMaxCol() + 1;
- while (right > 0)
- {
- if (GetColumnWidth(iColumnStart) > 0)
- SendMessage(WM_HSCROLL, SB_LINERIGHT, 0);
- right--;
- iColumnStart++;
- }
- iColumnStart = VisibleCells.GetMinCol() - 1;
- while (left > 0)
- {
- if (GetColumnWidth(iColumnStart) > 0)
- SendMessage(WM_HSCROLL, SB_LINELEFT, 0);
- left--;
- iColumnStart--;
- }
- iRowStart = VisibleCells.GetMaxRow() + 1;
- while (down > 0)
- {
- if (GetRowHeight(iRowStart) > 0)
- SendMessage(WM_VSCROLL, SB_LINEDOWN, 0);
- down--;
- iRowStart++;
- }
- iRowStart = VisibleCells.GetMinRow() - 1;
- while (up > 0)
- {
- if (GetRowHeight(iRowStart) > 0)
- SendMessage(WM_VSCROLL, SB_LINEUP, 0);
- up--;
- iRowStart--;
- }
- // Move one more if we only see a snall bit of the cell
- CRect rectCell;
- if (!GetCellRect(nRow, nCol, rectCell))
- {
- pFocusWnd->SetFocus();
- return;
- }
- GetClientRect(rectWindow);
- // The previous fix was fixed properly by Martin Richter <martin.richter@grutzeck.de>
- while (rectCell.right > rectWindow.right
- && rectCell.left > GetFixedColumnWidth())
- {
- SendMessage(WM_HSCROLL, SB_LINERIGHT, 0);
- if (!GetCellRect(nRow, nCol, rectCell))
- {
- pFocusWnd->SetFocus();
- return;
- }
- }
- while (rectCell.bottom > rectWindow.bottom
- && rectCell.top > GetFixedRowHeight())
- {
- SendMessage(WM_VSCROLL, SB_LINEDOWN, 0);
- if (!GetCellRect(nRow, nCol, rectCell))
- {
- pFocusWnd->SetFocus();
- return;
- }
- }
- // restore focus to whoever owned it
- pFocusWnd->SetFocus();
- }
- BOOL CGridCtrl::IsCellEditable(CCellID &cell) const
- {
- return IsCellEditable(cell.row, cell.col);
- }
- BOOL CGridCtrl::IsCellEditable(int nRow, int nCol) const
- {
- return IsEditable() && ((GetItemState(nRow, nCol) & GVIS_READONLY) != GVIS_READONLY);
- }
- BOOL CGridCtrl::IsCellSelected(CCellID &cell) const
- {
- return IsCellSelected(cell.row, cell.col);
- }
- BOOL CGridCtrl::IsCellSelected(int nRow, int nCol) const
- {
- if (GetVirtualMode())
- {
- if (!IsSelectable())
- return FALSE;
- CCellID cell;
- DWORD key = MAKELONG(nRow, nCol);
- return (m_SelectedCellMap.Lookup(key, (CCellID&)cell));
- }
- else
- return IsSelectable() && ((GetItemState(nRow, nCol) & GVIS_SELECTED) == GVIS_SELECTED);
- }
- BOOL CGridCtrl::IsCellVisible(CCellID cell)
- {
- return IsCellVisible(cell.row, cell.col);
- }
- BOOL CGridCtrl::IsCellVisible(int nRow, int nCol)
- {
- if (!IsWindow(m_hWnd))
- return FALSE;
- int x, y;
- CCellID TopLeft;
- if (nCol >= GetFixedColumnCount() || nRow >= GetFixedRowCount())
- {
- TopLeft = GetTopleftNonFixedCell();
- if (nCol >= GetFixedColumnCount() && nCol < TopLeft.col)
- return FALSE;
- if (nRow >= GetFixedRowCount() && nRow < TopLeft.row)
- return FALSE;
- }
- CRect rect;
- GetClientRect(rect);
- if (nCol < GetFixedColumnCount())
- {
- x = 0;
- for (int i = 0; i <= nCol; i++)
- {
- if (x >= rect.right)
- return FALSE;
- x += GetColumnWidth(i);
- }
- }
- else
- {
- x = GetFixedColumnWidth();
- for (int i = TopLeft.col; i <= nCol; i++)
- {
- if (x >= rect.right)
- return FALSE;
- x += GetColumnWidth(i);
- }
- }
- if (nRow < GetFixedRowCount())
- {
- y = 0;
- for (int i = 0; i <= nRow; i++)
- {
- if (y >= rect.bottom)
- return FALSE;
- y += GetRowHeight(i);
- }
- }
- else
- {
- if (nRow < TopLeft.row)
- return FALSE;
- y = GetFixedRowHeight();
- for (int i = TopLeft.row; i <= nRow; i++)
- {
- if (y >= rect.bottom)
- return FALSE;
- y += GetRowHeight(i);
- }
- }
- return TRUE;
- }
- BOOL CGridCtrl::InvalidateCellRect(const CCellID& cell)
- {
- return InvalidateCellRect(cell.row, cell.col);
- }
- BOOL CGridCtrl::InvalidateCellRect(const int row, const int col)
- {
- if (!::IsWindow(GetSafeHwnd()) || !m_bAllowDraw)
- return FALSE;
- if (!IsValid(row, col))
- return FALSE;
- if (!IsCellVisible(row, col))
- return FALSE;
- CRect rect;
- if (!GetCellRect(row, col, rect))
- return FALSE;
- rect.right++;
- rect.bottom++;
- InvalidateRect(rect, TRUE);
- return TRUE;
- }
- BOOL CGridCtrl::InvalidateCellRect(const CCellRange& cellRange)
- {
- ASSERT(IsValid(cellRange));
- if (!::IsWindow(GetSafeHwnd()) || !m_bAllowDraw)
- return FALSE;
- CCellRange visibleCellRange = GetVisibleNonFixedCellRange().Intersect(cellRange);
- CRect rect;
- if (!GetCellRangeRect(visibleCellRange, rect))
- return FALSE;
- rect.right++;
- rect.bottom++;
- InvalidateRect(rect, TRUE);
- return TRUE;
- }
- /////////////////////////////////////////////////////////////////////////////
- // CGridCtrl Mouse stuff
- // Handles mouse wheel notifications
- // Note - if this doesn't work for win95 then use OnRegisteredMouseWheel instead
- #if !defined(_WIN32_WCE) && (_MFC_VER >= 0x0421)
- BOOL CGridCtrl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
- {
- // A m_nRowsPerWheelNotch value less than 0 indicates that the mouse
- // wheel scrolls whole pages, not just lines.
- if (m_nRowsPerWheelNotch == -1)
- {
- int nPagesScrolled = zDelta / 120;
- if (nPagesScrolled > 0)
- for (int i = 0; i < nPagesScrolled; i++)
- PostMessage(WM_VSCROLL, SB_PAGEUP, 0);
- else
- for (int i = 0; i > nPagesScrolled; i--)
- PostMessage(WM_VSCROLL, SB_PAGEDOWN, 0);
- }
- else
- {
- int nRowsScrolled = m_nRowsPerWheelNotch * zDelta / 120;
- if (nRowsScrolled > 0)
- for (int i = 0; i < nRowsScrolled; i++)
- PostMessage(WM_VSCROLL, SB_LINEUP, 0);
- else
- for (int i = 0; i > nRowsScrolled; i--)
- PostMessage(WM_VSCROLL, SB_LINEDOWN, 0);
- }
- return CWnd::OnMouseWheel(nFlags, zDelta, pt);
- }
- #endif // !defined(_WIN32_WCE) && (_MFC_VER >= 0x0421)
- void CGridCtrl::OnMouseMove(UINT /*nFlags*/, CPoint point)
- {
- CRect rect;
- GetClientRect(rect);
- #ifndef GRIDCONTROL_NO_DRAGDROP
- // If outside client area, return (unless we are drag n dropping)
- if (m_MouseMode != MOUSE_DRAGGING && !rect.PtInRect(point))
- return;
- #endif
- // Sometimes a MOUSEMOVE message can come after the left buttons
- // has been let go, but before the BUTTONUP message hs been processed.
- // We'll keep track of mouse buttons manually to avoid this.
- // All bMouseButtonDown's have been replaced with the member m_bLMouseButtonDown
- // BOOL bMouseButtonDown = ((nFlags & MK_LBUTTON) == MK_LBUTTON);
- // If the left mouse button is up, then test to see if row/column sizing is imminent
- if (!m_bLMouseButtonDown ||
- (m_bLMouseButtonDown && m_MouseMode == MOUSE_NOTHING))
- {
- if (m_bAllowColumnResize && MouseOverColumnResizeArea(point))
- {
- if (m_MouseMode != MOUSE_OVER_COL_DIVIDE)
- {
- #ifndef _WIN32_WCE_NO_CURSOR
- SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZEWE));
- #endif
- m_MouseMode = MOUSE_OVER_COL_DIVIDE;
- }
- }
- else if (m_bAllowRowResize && MouseOverRowResizeArea(point))
- {
- if (m_MouseMode != MOUSE_OVER_ROW_DIVIDE)
- {
- #ifndef _WIN32_WCE_NO_CURSOR
- SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZENS));
- #endif
- m_MouseMode = MOUSE_OVER_ROW_DIVIDE;
- }
- }
- else if (m_MouseMode != MOUSE_NOTHING)
- {
- #ifndef _WIN32_WCE_NO_CURSOR
- SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
- #endif
- m_MouseMode = MOUSE_NOTHING;
- }
- if (m_MouseMode == MOUSE_NOTHING)
- {
- CGridCellBase* pCell = NULL;
- CCellID idCurrentCell;
- if (!GetVirtualMode() || m_bTitleTips)
- {
- // Let the cell know that a big fat cursor is currently hovering
- // over it.
- idCurrentCell = GetCellFromPt(point);
- pCell = GetCell(idCurrentCell.row, idCurrentCell.col);
- if (pCell)
- pCell->OnMouseOver();
- }
- #ifndef GRIDCONTROL_NO_TITLETIPS
- // Titletips anyone? anyone?
- if (m_bTitleTips)
- {
- CRect TextRect, CellRect;
- if (pCell)
- {
- LPCTSTR szTipText = pCell->GetTipText();
- if (!m_bRMouseButtonDown
- && szTipText && szTipText[0]
- && !pCell->IsEditing()
- && GetCellRect(idCurrentCell.row, idCurrentCell.col, &TextRect)
- && pCell->GetTipTextRect(&TextRect)
- && GetCellRect(idCurrentCell.row, idCurrentCell.col, CellRect))
- {
- //TRACE0("Showing TitleTip\n");
- m_TitleTip.Show(TextRect, pCell->GetTipText(), 0, CellRect,
- pCell->GetFont(), GetTitleTipTextClr(), GetTitleTipBackClr());
- }
- }
- }
- #endif
- }
- m_LastMousePoint = point;
- return;
- }
- if (!IsValid(m_LeftClickDownCell))
- {
- m_LastMousePoint = point;
- return;
- }
- // If the left mouse button is down, then process appropriately
- if (m_bLMouseButtonDown)
- {
- switch (m_MouseMode)
- {
- case MOUSE_SELECT_ALL:
- break;
- case MOUSE_SELECT_COL:
- case MOUSE_SELECT_ROW:
- case MOUSE_SELECT_CELLS:
- {
- CCellID idCurrentCell = GetCellFromPt(point);
- if (!IsValid(idCurrentCell))
- return;
- if (idCurrentCell != GetFocusCell())
- {
- OnSelecting(idCurrentCell);
- // EFW - BUG FIX - Keep the appropriate cell row and/or
- // column focused. A fix in SetFocusCell() will place
- // the cursor in a non-fixed cell as needed.
- if ((idCurrentCell.row >= m_nFixedRows &&
- idCurrentCell.col >= m_nFixedCols) ||
- m_MouseMode == MOUSE_SELECT_COL ||
- m_MouseMode == MOUSE_SELECT_ROW)
- {
- SetFocusCell(idCurrentCell);
- }
- }
- break;
- }
- case MOUSE_SIZING_COL:
- {
- CDC* pDC = GetDC();
- if (!pDC)
- break;
- CRect oldInvertedRect(m_LastMousePoint.x, rect.top,
- m_LastMousePoint.x + 2, rect.bottom);
- pDC->InvertRect(&oldInvertedRect);
- CRect newInvertedRect(point.x, rect.top,
- point.x + 2, rect.bottom);
- pDC->InvertRect(&newInvertedRect);
- ReleaseDC(pDC);
- }
- break;
- case MOUSE_SIZING_ROW:
- {
- CDC* pDC = GetDC();
- if (!pDC)
- break;
- CRect oldInvertedRect(rect.left, m_LastMousePoint.y,
- rect.right, m_LastMousePoint.y + 2);
- pDC->InvertRect(&oldInvertedRect);
- CRect newInvertedRect(rect.left, point.y,
- rect.right, point.y + 2);
- pDC->InvertRect(&newInvertedRect);
- ReleaseDC(pDC);
- }
- break;
- #ifndef GRIDCONTROL_NO_DRAGDROP
- case MOUSE_PREPARE_EDIT:
- case MOUSE_PREPARE_DRAG:
- m_MouseMode = MOUSE_PREPARE_DRAG;
- OnBeginDrag();
- break;
- #endif
- }
- }
- m_LastMousePoint = point;
- }
- // Returns the point inside the cell that was clicked (coords relative to cell top left)
- CPoint CGridCtrl::GetPointClicked(int nRow, int nCol, const CPoint& point)
- {
- CPoint PointCellOrigin;
- if (!GetCellOrigin(nRow, nCol, &PointCellOrigin))
- return CPoint(0, 0);
- CPoint PointClickedCellRelative(point);
- PointClickedCellRelative -= PointCellOrigin;
- return PointClickedCellRelative;
- }
- void CGridCtrl::OnLButtonDblClk(UINT nFlags, CPoint point)
- {
- //TRACE0("CGridCtrl::OnLButtonDblClk\n");
- CCellID cell = GetCellFromPt(point);
- if (!IsValid(cell))
- {
- //ASSERT(FALSE);
- return;
- }
- #ifdef _WIN32_WCE
- if (MouseOverColumnResizeArea(point))
- #else
- if (m_MouseMode == MOUSE_OVER_COL_DIVIDE)
- #endif
- {
- CPoint start;
- if (!GetCellOrigin(0, cell.col, &start))
- return;
- if (point.x - start.x < m_nResizeCaptureRange) // Clicked right of border
- cell.col--;
- // ignore columns that are hidden and look left towards first visible column
- BOOL bFoundVisible = FALSE;
- while (cell.col >= 0)
- {
- if (GetColumnWidth(cell.col) > 0)
- {
- bFoundVisible = TRUE;
- break;
- }
- cell.col--;
- }
- if (!bFoundVisible)
- return;
- AutoSizeColumn(cell.col, GetAutoSizeStyle());
- Invalidate();
- }
- #ifdef _WIN32_WCE
- else if (MouseOverRowResizeArea(point))
- #else
- else if (m_MouseMode == MOUSE_OVER_ROW_DIVIDE)
- #endif
- {
- CPoint start;
- if (!GetCellOrigin(0, cell.col, &start))
- return;
- if (point.y - start.y < m_nResizeCaptureRange) // Clicked below border
- cell.row--;
- // ignore rows that are hidden and look up towards first visible row
- BOOL bFoundVisible = FALSE;
- while (cell.row >= 0)
- {
- if (GetRowHeight(cell.row) > 0)
- {
- bFoundVisible = TRUE;
- break;
- }
- cell.row--;
- }
- if (!bFoundVisible)
- return;
- AutoSizeRow(cell.row);
- Invalidate();
- }
- else if (m_MouseMode == MOUSE_NOTHING)
- {
- CPoint pointClickedRel;
- pointClickedRel = GetPointClicked(cell.row, cell.col, point);
- CGridCellBase* pCell = NULL;
- if (IsValid(cell))
- pCell = GetCell(cell.row, cell.col);
- // Clicked in the text area? Only then will cell selection work
- BOOL bInTextArea = FALSE;
- if (pCell)
- {
- CRect rectCell;
- if (GetCellRect(cell.row, cell.col, rectCell) && pCell->GetTextRect(rectCell))
- bInTextArea = rectCell.PtInRect(point);
- }
- if (cell.row >= m_nFixedRows && IsValid(m_LeftClickDownCell) &&
- cell.col >= m_nFixedCols && bInTextArea)
- {
- OnEditCell(cell.row, cell.col, pointClickedRel, VK_LBUTTON);
- }
- else if (m_bListMode)
- {
- if (!IsValid(cell))
- return;
- if (cell.row >= m_nFixedRows && cell.col >= m_nFixedCols && bInTextArea)
- OnEditCell(cell.row, cell.col, pointClickedRel, VK_LBUTTON);
- }
- if (IsValid(cell))
- {
- CGridCellBase* pCell = GetCell(cell.row, cell.col);
- if (pCell)
- pCell->OnDblClick(pointClickedRel);
- SendMessageToParent(cell.row, cell.col, NM_DBLCLK);
- }
- }
- CWnd::OnLButtonDblClk(nFlags, point);
- }
- void CGridCtrl::OnLButtonDown(UINT nFlags, CPoint point)
- {
- #ifdef GRIDCONTROL_USE_TITLETIPS
- // EFW - Bug Fix
- m_TitleTip.Hide(); // hide any titletips
- #endif
- // TRACE0("CGridCtrl::OnLButtonDown\n");
- // CWnd::OnLButtonDown(nFlags, point);
- SetFocus();
- m_bLMouseButtonDown = TRUE;
- m_LeftClickDownPoint = point;
- m_LeftClickDownCell = GetCellFromPt(point);
- if (!IsValid(m_LeftClickDownCell))
- return;
- // If the SHIFT key is not down, then the start of the selection area should be the
- // cell just clicked. Otherwise, keep the previous selection-start-cell so the user
- // can add to their previous cell selections in an intuitive way. If no selection-
- // start-cell has been specified, then set it's value here and now.
- if ((nFlags & MK_SHIFT) != MK_SHIFT)
- m_SelectionStartCell = m_LeftClickDownCell;
- else
- {
- if (!IsValid(m_SelectionStartCell))
- m_SelectionStartCell = m_idCurrentCell;
- }
- EndEditing();
- // tell the cell about it
- CGridCellBase* pCell = GetCell(m_LeftClickDownCell.row, m_LeftClickDownCell.col);
- if (pCell)
- pCell->OnClickDown(GetPointClicked(m_LeftClickDownCell.row, m_LeftClickDownCell.col, point));
- // Clicked in the text area? Only then will cell selection work
- BOOL bInTextArea = FALSE;
- if (pCell)
- {
- CRect rectCell;
- if (GetCellRect(m_LeftClickDownCell.row, m_LeftClickDownCell.col, rectCell) &&
- pCell->GetTextRect(rectCell))
- {
- bInTextArea = rectCell.PtInRect(point);
- }
- }
- // If the user clicks on the current cell, then prepare to edit it.
- // (If the user moves the mouse, then dragging occurs)
- if (m_LeftClickDownCell == m_idCurrentCell &&
- !(nFlags & MK_CONTROL) && bInTextArea &&
- IsCellEditable(m_LeftClickDownCell))
- {
- m_MouseMode = MOUSE_PREPARE_EDIT;
- return;
- }
- // If the user clicks on a selected cell, then prepare to drag it.
- // (If the user moves the mouse, then dragging occurs)
- else if (IsCellSelected(m_LeftClickDownCell))
- {
- // If control is pressed then unselect the cell or row (depending on the list mode)
- if (nFlags & MK_CONTROL)
- {
- SetFocusCell(m_LeftClickDownCell);
- if (GetListMode())
- SelectRows(m_LeftClickDownCell, TRUE, FALSE);
- else
- SelectCells(m_LeftClickDownCell, TRUE, FALSE);
- return;
- }
- #ifndef GRIDCONTROL_NO_DRAGDROP
- else if (m_bAllowDragAndDrop)
- m_MouseMode = MOUSE_PREPARE_DRAG;
- #endif
- }
- else if (m_MouseMode != MOUSE_OVER_COL_DIVIDE &&
- m_MouseMode != MOUSE_OVER_ROW_DIVIDE)
- {
- SetFocusCell(-1, -1);
- if (GetRowCount() > GetFixedRowCount() &&
- GetColumnCount() > GetFixedColumnCount())
- SetFocusCell(max(m_LeftClickDownCell.row, m_nFixedRows),
- max(m_LeftClickDownCell.col, m_nFixedCols));
- }
- SetCapture();
- if (m_MouseMode == MOUSE_NOTHING)
- {
- if (m_bAllowColumnResize && MouseOverColumnResizeArea(point))
- {
- if (m_MouseMode != MOUSE_OVER_COL_DIVIDE)
- {
- #ifndef _WIN32_WCE_NO_CURSOR
- SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZEWE));
- #endif
- m_MouseMode = MOUSE_OVER_COL_DIVIDE;
- }
- }
- else if (m_bAllowRowResize && MouseOverRowResizeArea(point))
- {
- if (m_MouseMode != MOUSE_OVER_ROW_DIVIDE)
- {
- #ifndef _WIN32_WCE_NO_CURSOR
- SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZENS));
- #endif
- m_MouseMode = MOUSE_OVER_ROW_DIVIDE;
- }
- }
- // else if (m_MouseMode != MOUSE_NOTHING)
- //{
- // SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
- // m_MouseMode = MOUSE_NOTHING;
- //}
- }
- if (m_MouseMode == MOUSE_OVER_COL_DIVIDE) // sizing column
- {
- m_MouseMode = MOUSE_SIZING_COL;
- // Kludge for if we are over the last column...
- if (GetColumnWidth(GetColumnCount() - 1) < m_nResizeCaptureRange)
- {
- CRect VisRect;
- GetVisibleNonFixedCellRange(VisRect);
- if (abs(point.x - VisRect.right) < m_nResizeCaptureRange)
- m_LeftClickDownCell.col = GetColumnCount() - 1;
- }
- CPoint start;
- if (!GetCellOrigin(0, m_LeftClickDownCell.col, &start))
- return;
- if (!m_bHiddenColUnhide)
- {
- // ignore columns that are hidden and look left towards first visible column
- BOOL bLookForVisible = TRUE;
- BOOL bIsCellRightBorder = point.x - start.x >= m_nResizeCaptureRange;
- if (bIsCellRightBorder
- && m_LeftClickDownCell.col + 1 >= GetColumnCount())
- {
- // clicked on last column's right border
- // if last column is visible, don't do anything
- if (m_LeftClickDownCell.col >= 0)
- bLookForVisible = FALSE;
- }
- if (bLookForVisible)
- {
- // clicked on column divider other than last right border
- BOOL bFoundVisible = FALSE;
- int iOffset = 1;
- if (bIsCellRightBorder)
- iOffset = 0;
- while (m_LeftClickDownCell.col - iOffset >= 0)
- {
- if (GetColumnWidth(m_LeftClickDownCell.col - iOffset) > 0)
- {
- bFoundVisible = TRUE;
- break;
- }
- m_LeftClickDownCell.col--;
- }
- if (!bFoundVisible)
- return;
- }
- }
- CRect rect;
- GetClientRect(rect);
- CRect invertedRect(point.x, rect.top, point.x + 2, rect.bottom);
- CDC* pDC = GetDC();
- if (pDC)
- {
- pDC->InvertRect(&invertedRect);
- ReleaseDC(pDC);
- }
- // If we clicked to the right of the colimn divide, then reset the click-down cell
- // as the cell to the left of the column divide - UNLESS we clicked on the last column
- // and the last column is teensy (kludge fix)
- if (point.x - start.x < m_nResizeCaptureRange)
- {
- if (m_LeftClickDownCell.col < GetColumnCount() - 1 ||
- GetColumnWidth(GetColumnCount() - 1) >= m_nResizeCaptureRange)
- {
- if (!GetCellOrigin(0, --m_LeftClickDownCell.col, &start))
- return;
- }
- }
- // Allow a cell resize width no greater than that which can be viewed within
- // the grid itself
- int nMaxCellWidth = rect.Width() - GetFixedColumnWidth();
- rect.left = start.x + 1;
- rect.right = rect.left + nMaxCellWidth;
- ClientToScreen(rect);
- #ifndef _WIN32_WCE_NO_CURSOR
- ClipCursor(rect);
- #endif
- }
- else if (m_MouseMode == MOUSE_OVER_ROW_DIVIDE) // sizing row
- {
- m_MouseMode = MOUSE_SIZING_ROW;
- // Kludge for if we are over the last column...
- if (GetRowHeight(GetRowCount() - 1) < m_nResizeCaptureRange)
- {
- CRect VisRect;
- GetVisibleNonFixedCellRange(VisRect);
- if (abs(point.y - VisRect.bottom) < m_nResizeCaptureRange)
- m_LeftClickDownCell.row = GetRowCount() - 1;
- }
- CPoint start;
- if (!GetCellOrigin(m_LeftClickDownCell, &start))
- return;
- if (!m_bHiddenRowUnhide)
- {
- // ignore rows that are hidden and look up towards first visible row
- BOOL bLookForVisible = TRUE;
- BOOL bIsCellBottomBorder = point.y - start.y >= m_nResizeCaptureRange;
- if (bIsCellBottomBorder
- && m_LeftClickDownCell.row + 1 >= GetRowCount())
- {
- // clicked on last row's bottom border
- // if last row is visible, don't do anything
- if (m_LeftClickDownCell.row >= 0)
- bLookForVisible = FALSE;
- }
- if (bLookForVisible)
- {
- // clicked on row divider other than last bottom border
- BOOL bFoundVisible = FALSE;
- int iOffset = 1;
- if (bIsCellBottomBorder)
- iOffset = 0;
- while (m_LeftClickDownCell.row - iOffset >= 0)
- {
- if (GetRowHeight(m_LeftClickDownCell.row - iOffset) > 0)
- {
- bFoundVisible = TRUE;
- break;
- }
- m_LeftClickDownCell.row--;
- }
- if (!bFoundVisible)
- return;
- }
- }
- CRect rect;
- GetClientRect(rect);
- CRect invertedRect(rect.left, point.y, rect.right, point.y + 2);
- CDC* pDC = GetDC();
- if (pDC)
- {
- pDC->InvertRect(&invertedRect);
- ReleaseDC(pDC);
- }
- // If we clicked below the row divide, then reset the click-down cell
- // as the cell above the row divide - UNLESS we clicked on the last row
- // and the last row is teensy (kludge fix)
- if (point.y - start.y < m_nResizeCaptureRange) // clicked below border
- {
- if (m_LeftClickDownCell.row < GetRowCount() - 1 ||
- GetRowHeight(GetRowCount() - 1) >= m_nResizeCaptureRange)
- {
- if (!GetCellOrigin(--m_LeftClickDownCell.row, 0, &start))
- return;
- }
- }
- int nMaxCellHeight = rect.Height() - GetFixedRowHeight();
- rect.top = start.y + 1;
- rect.bottom = rect.top + nMaxCellHeight;
- ClientToScreen(rect);
- #ifndef _WIN32_WCE_NO_CURSOR
- ClipCursor(rect);
- #endif
- }
- else
- #ifndef GRIDCONTROL_NO_DRAGDROP
- if (m_MouseMode != MOUSE_PREPARE_DRAG) // not sizing or editing -- selecting
- #endif
- {
- SendMessageToParent(m_LeftClickDownCell.row, m_LeftClickDownCell.col, GVN_SELCHANGING);
- // If Ctrl pressed, save the current cell selection. This will get added
- // to the new cell selection at the end of the cell selection process
- m_PrevSelectedCellMap.RemoveAll();
- if (nFlags & MK_CONTROL)
- {
- for (POSITION pos = m_SelectedCellMap.GetStartPosition(); pos != NULL;)
- {
- DWORD key;
- CCellID cell;
- m_SelectedCellMap.GetNextAssoc(pos, key, (CCellID&)cell);
- m_PrevSelectedCellMap.SetAt(key, cell);
- }
- }
- if (m_LeftClickDownCell.row < GetFixedRowCount())
- OnFixedRowClick(m_LeftClickDownCell);
- else if (m_LeftClickDownCell.col < GetFixedColumnCount())
- OnFixedColumnClick(m_LeftClickDownCell);
- else
- {
- m_MouseMode = m_bListMode ? MOUSE_SELECT_ROW : MOUSE_SELECT_CELLS;
- OnSelecting(m_LeftClickDownCell);
- m_nTimerID = SetTimer(WM_LBUTTONDOWN, m_nTimerInterval, 0);
- }
- }
- m_LastMousePoint = point;
- }
- void CGridCtrl::OnLButtonUp(UINT nFlags, CPoint point)
- {
- // TRACE0("CGridCtrl::OnLButtonUp\n");
- CWnd::OnLButtonUp(nFlags, point);
- m_bLMouseButtonDown = FALSE;
- #ifndef _WIN32_WCE_NO_CURSOR
- ClipCursor(NULL);
- #endif
- if (GetCapture()->GetSafeHwnd() == GetSafeHwnd())
- {
- ReleaseCapture();
- KillTimer(m_nTimerID);
- m_nTimerID = 0;
- }
- CPoint pointClickedRel;
- pointClickedRel = GetPointClicked(m_idCurrentCell.row, m_idCurrentCell.col, point);
- // m_MouseMode == MOUSE_PREPARE_EDIT only if user clicked down on current cell
- // and then didn't move mouse before clicking up (releasing button)
- if (m_MouseMode == MOUSE_PREPARE_EDIT)
- {
- OnEditCell(m_idCurrentCell.row, m_idCurrentCell.col, pointClickedRel, VK_LBUTTON);
- }
- #ifndef GRIDCONTROL_NO_DRAGDROP
- // m_MouseMode == MOUSE_PREPARE_DRAG only if user clicked down on a selected cell
- // and then didn't move mouse before clicking up (releasing button)
- else if (m_MouseMode == MOUSE_PREPARE_DRAG)
- {
- CGridCellBase* pCell = GetCell(m_idCurrentCell.row, m_idCurrentCell.col);
- if (pCell)
- pCell->OnClick(GetPointClicked(m_idCurrentCell.row, m_idCurrentCell.col, point));
- SendMessageToParent(m_LeftClickDownCell.row, m_LeftClickDownCell.col, NM_CLICK);
- SendMessageToParent(m_LeftClickDownCell.row, m_LeftClickDownCell.col, GVN_SELCHANGING);
- ResetSelectedRange();
- SendMessageToParent(m_idCurrentCell.row, m_idCurrentCell.col, GVN_SELCHANGED);
- }
- #endif
- else if (m_MouseMode == MOUSE_SIZING_COL)
- {
- CRect rect;
- GetClientRect(rect);
- CRect invertedRect(m_LastMousePoint.x, rect.top, m_LastMousePoint.x + 2, rect.bottom);
- CDC* pDC = GetDC();
- if (pDC)
- {
- pDC->InvertRect(&invertedRect);
- ReleaseDC(pDC);
- }
- if (m_LeftClickDownPoint != point && (point.x != 0 || point.y != 0)) // 0 pt fix by email1@bierling.net
- {
- CPoint start;
- if (!GetCellOrigin(m_LeftClickDownCell, &start))
- return;
- int nColumnWidth = max(point.x - start.x, m_bAllowColHide ? 0 : 1);
- SetColumnWidth(m_LeftClickDownCell.col, nColumnWidth);
- ResetScrollBars();
- Invalidate();
- }
- }
- else if (m_MouseMode == MOUSE_SIZING_ROW)
- {
- CRect rect;
- GetClientRect(rect);
- CRect invertedRect(rect.left, m_LastMousePoint.y, rect.right, m_LastMousePoint.y + 2);
- CDC* pDC = GetDC();
- if (pDC)
- {
- pDC->InvertRect(&invertedRect);
- ReleaseDC(pDC);
- }
- if (m_LeftClickDownPoint != point && (point.x != 0 || point.y != 0)) // 0 pt fix by email1@bierling.net
- {
- CPoint start;
- if (!GetCellOrigin(m_LeftClickDownCell, &start))
- return;
- int nRowHeight = max(point.y - start.y, m_bAllowRowHide ? 0 : 1);
- SetRowHeight(m_LeftClickDownCell.row, nRowHeight);
- ResetScrollBars();
- Invalidate();
- }
- }
- else
- {
- SendMessageToParent(m_idCurrentCell.row, m_idCurrentCell.col, GVN_SELCHANGED);
- CGridCellBase* pCell = GetCell(m_idCurrentCell.row, m_idCurrentCell.col);
- if (pCell)
- pCell->OnClick(GetPointClicked(m_idCurrentCell.row, m_idCurrentCell.col, point));
- SendMessageToParent(m_LeftClickDownCell.row, m_LeftClickDownCell.col, NM_CLICK);
- }
- m_MouseMode = MOUSE_NOTHING;
- #ifndef _WIN32_WCE_NO_CURSOR
- SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
- #endif
- if (!IsValid(m_LeftClickDownCell))
- return;
- CWnd *pOwner = GetOwner();
- if (pOwner && IsWindow(pOwner->m_hWnd))
- pOwner->PostMessage(WM_COMMAND, MAKELONG(GetDlgCtrlID(), BN_CLICKED),
- (LPARAM)GetSafeHwnd());
- }
- #ifndef _WIN32_WCE
- void CGridCtrl::OnRButtonDown(UINT nFlags, CPoint point)
- {
- CWnd::OnRButtonDown(nFlags, point);
- m_bRMouseButtonDown = TRUE;
- #ifdef GRIDCONTROL_USE_TITLETIPS
- //TRACE0("Hiding TitleTip\n");
- m_TitleTip.Hide(); // hide any titletips
- #endif
- }
- // EFW - Added to forward right click to parent so that a context
- // menu can be shown without deriving a new grid class.
- void CGridCtrl::OnRButtonUp(UINT nFlags, CPoint point)
- {
- CWnd::OnRButtonUp(nFlags, point);
- m_bRMouseButtonDown = FALSE;
- CCellID FocusCell;
- FocusCell = GetCellFromPt(point);
- EndEditing(); // Auto-destroy any InPlaceEdit's
- // If not a valid cell, pass -1 for row and column
- if (!IsValid(FocusCell))
- SendMessageToParent(-1, -1, NM_RCLICK);
- else
- {
- SetFocusCell(-1, -1);
- SetFocusCell(max(FocusCell.row, m_nFixedRows),
- max(FocusCell.col, m_nFixedCols));
- // tell the cell about it
- CGridCellBase* pCell = GetCell(FocusCell.row, FocusCell.col);
- if (pCell)
- pCell->OnRClick(GetPointClicked(FocusCell.row, FocusCell.col, point));
- SendMessageToParent(FocusCell.row, FocusCell.col, NM_RCLICK);
- }
- }
- #endif
- #if !defined(_WIN32_WCE_NO_PRINTING) && !defined(GRIDCONTROL_NO_PRINTING)
- /////////////////////////////////////////////////////////////////////////////
- // CGridCtrl printing
- // EFW - New print margin support functions
- void CGridCtrl::SetPrintMarginInfo(int nHeaderHeight, int nFooterHeight,
- int nLeftMargin, int nRightMargin, int nTopMargin,
- int nBottomMargin, int nGap)
- {
- // If any parameter is -1, keep the existing setting
- if (nHeaderHeight > -1)
- m_nHeaderHeight = nHeaderHeight;
- if (nFooterHeight > -1)
- m_nFooterHeight = nFooterHeight;
- if (nLeftMargin > -1)
- m_nLeftMargin = nLeftMargin;
- if (nRightMargin > -1)
- m_nRightMargin = nRightMargin;
- if (nTopMargin > -1)
- m_nTopMargin = nTopMargin;
- if (nBottomMargin > -1)
- m_nBottomMargin = nBottomMargin;
- if (nGap > -1)
- m_nGap = nGap;
- }
- void CGridCtrl::GetPrintMarginInfo(int &nHeaderHeight, int &nFooterHeight,
- int &nLeftMargin, int &nRightMargin, int &nTopMargin,
- int &nBottomMargin, int &nGap)
- {
- nHeaderHeight = m_nHeaderHeight;
- nFooterHeight = m_nFooterHeight;
- nLeftMargin = m_nLeftMargin;
- nRightMargin = m_nRightMargin;
- nTopMargin = m_nTopMargin;
- nBottomMargin = m_nBottomMargin;
- nGap = m_nGap;
- }
- void CGridCtrl::Print(CPrintDialog* pPrntDialog /*=NULL*/)
- {
- CDC dc;
- if (pPrntDialog == NULL)
- {
- CPrintDialog printDlg(FALSE);
- if (printDlg.DoModal() != IDOK) // Get printer settings from user
- return;
- dc.Attach(printDlg.GetPrinterDC()); // attach a printer DC
- }
- else
- dc.Attach(pPrntDialog->GetPrinterDC()); // attach a printer DC
- dc.m_bPrinting = TRUE;
- CString strTitle;
- strTitle.LoadString(AFX_IDS_APP_TITLE);
- if (strTitle.IsEmpty())
- {
- CWnd *pParentWnd = GetParent();
- while (pParentWnd)
- {
- pParentWnd->GetWindowText(strTitle);
- if (strTitle.GetLength()) // can happen if it is a CView, CChildFrm has the title
- break;
- pParentWnd = pParentWnd->GetParent();
- }
- }
- DOCINFO di; // Initialise print doc details
- memset(&di, 0, sizeof(DOCINFO));
- di.cbSize = sizeof(DOCINFO);
- di.lpszDocName = strTitle;
- BOOL bPrintingOK = dc.StartDoc(&di); // Begin a new print job
- CPrintInfo Info;
- Info.m_rectDraw.SetRect(0, 0, dc.GetDeviceCaps(HORZRES), dc.GetDeviceCaps(VERTRES));
- OnBeginPrinting(&dc, &Info); // Initialise printing
- for (UINT page = Info.GetMinPage(); page <= Info.GetMaxPage() && bPrintingOK; page++)
- {
- dc.StartPage(); // begin new page
- Info.m_nCurPage = page;
- OnPrint(&dc, &Info); // Print page
- bPrintingOK = (dc.EndPage() > 0); // end page
- }
- OnEndPrinting(&dc, &Info); // Clean up after printing
- if (bPrintingOK)
- dc.EndDoc(); // end a print job
- else
- dc.AbortDoc(); // abort job.
- dc.Detach(); // detach the printer DC
- }
- /////////////////////////////////////////////////////////////////////////////
- // CGridCtrl printing overridables - for Doc/View print/print preview framework
- // EFW - Various changes in the next few functions to support the
- // new print margins and a few other adjustments.
- void CGridCtrl::OnBeginPrinting(CDC *pDC, CPrintInfo *pInfo)
- {
- // OnBeginPrinting() is called after the user has committed to
- // printing by OK'ing the Print dialog, and after the framework
- // has created a CDC object for the printer or the preview view.
- // This is the right opportunity to set up the page range.
- // Given the CDC object, we can determine how many rows will
- // fit on a page, so we can in turn determine how many printed
- // pages represent the entire document.
- ASSERT(pDC && pInfo);
- if (!pDC || !pInfo) return;
- // Get a DC for the current window (will be a screen DC for print previewing)
- CDC *pCurrentDC = GetDC(); // will have dimensions of the client area
- if (!pCurrentDC) return;
- CSize PaperPixelsPerInch(pDC->GetDeviceCaps(LOGPIXELSX), pDC->GetDeviceCaps(LOGPIXELSY));
- CSize ScreenPixelsPerInch(pCurrentDC->GetDeviceCaps(LOGPIXELSX), pCurrentDC->GetDeviceCaps(LOGPIXELSY));
- // Create the printer font
- int nFontSize = -10;
- CString strFontName = _T("Arial");
- m_PrinterFont.CreateFont(nFontSize, 0, 0, 0, FW_NORMAL, 0, 0, 0, DEFAULT_CHARSET,
- OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS, DEFAULT_QUALITY,
- DEFAULT_PITCH | FF_DONTCARE, strFontName);
- CFont *pOldFont = pDC->SelectObject(&m_PrinterFont);
- // Get the average character width (in GridCtrl units) and hence the margins
- m_CharSize = pDC->GetTextExtent(_T("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSATUVWXYZ"), 52);
- m_CharSize.cx /= 52;
- int nMargins = (m_nLeftMargin + m_nRightMargin)*m_CharSize.cx;
- // Get the page sizes (physical and logical)
- m_PaperSize = CSize(pDC->GetDeviceCaps(HORZRES), pDC->GetDeviceCaps(VERTRES));
- if (m_bWysiwygPrinting)
- {
- m_LogicalPageSize.cx = ScreenPixelsPerInch.cx * m_PaperSize.cx / PaperPixelsPerInch.cx * 3 / 4;
- m_LogicalPageSize.cy = ScreenPixelsPerInch.cy * m_PaperSize.cy / PaperPixelsPerInch.cy * 3 / 4;
- }
- else
- {
- m_PaperSize = CSize(pDC->GetDeviceCaps(HORZRES), pDC->GetDeviceCaps(VERTRES));
- m_LogicalPageSize.cx = GetVirtualWidth() + nMargins;
- #ifdef _WIN32_WCE
- m_LogicalPageSize.cy = (m_LogicalPageSize.cx * m_PaperSize.cy) / m_PaperSize.cx;
- #else
- m_LogicalPageSize.cy = MulDiv(m_LogicalPageSize.cx, m_PaperSize.cy, m_PaperSize.cx);
- #endif
- }
- m_nPageHeight = m_LogicalPageSize.cy - GetFixedRowHeight()
- - (m_nHeaderHeight + m_nFooterHeight + 2 * m_nGap)*m_CharSize.cy;
- // Get the number of pages. Assumes no row is bigger than the page size.
- int nTotalRowHeight = 0;
- m_nNumPages = 1;
- for (int row = GetFixedRowCount(); row < GetRowCount(); row++)
- {
- nTotalRowHeight += GetRowHeight(row);
- if (nTotalRowHeight > m_nPageHeight) {
- m_nNumPages++;
- nTotalRowHeight = GetRowHeight(row);
- }
- }
- // now, figure out how many additional pages must print out if rows ARE bigger
- // than page size
- int iColumnOffset = 0;
- int i1;
- for (i1 = 0; i1 < GetFixedColumnCount(); i1++)
- {
- iColumnOffset += GetColumnWidth(i1);
- }
- m_nPageWidth = m_LogicalPageSize.cx - iColumnOffset
- - nMargins;
- m_nPageMultiplier = 1;
- if (m_bWysiwygPrinting)
- {
- int iTotalRowWidth = 0;
- for (i1 = GetFixedColumnCount(); i1 < GetColumnCount(); i1++)
- {
- iTotalRowWidth += GetColumnWidth(i1);
- if (iTotalRowWidth > m_nPageWidth)
- {
- m_nPageMultiplier++;
- iTotalRowWidth = GetColumnWidth(i1);
- }
- }
- m_nNumPages *= m_nPageMultiplier;
- }
- // Set up the print info
- pInfo->SetMaxPage(m_nNumPages);
- pInfo->m_nCurPage = 1; // start printing at page# 1
- ReleaseDC(pCurrentDC);
- pDC->SelectObject(pOldFont);
- }
- void CGridCtrl::OnPrint(CDC *pDC, CPrintInfo *pInfo)
- {
- if (!pDC || !pInfo)
- return;
- //CRect rcPage(pInfo->m_rectDraw);
- CFont *pOldFont = pDC->SelectObject(&m_PrinterFont);
- // Set the page map mode to use GridCtrl units, and setup margin
- pDC->SetMapMode(MM_ANISOTROPIC);
- pDC->SetWindowExt(m_LogicalPageSize);
- pDC->SetViewportExt(m_PaperSize);
- pDC->SetWindowOrg(-m_nLeftMargin * m_CharSize.cx, 0);
- // Header
- pInfo->m_rectDraw.top = 0;
- pInfo->m_rectDraw.left = 0;
- pInfo->m_rectDraw.right = m_LogicalPageSize.cx - (m_nLeftMargin + m_nRightMargin) * m_CharSize.cx;
- pInfo->m_rectDraw.bottom = m_nHeaderHeight * m_CharSize.cy;
- PrintHeader(pDC, pInfo);
- pDC->OffsetWindowOrg(0, -m_nHeaderHeight * m_CharSize.cy);
- // Gap between header and column headings
- pDC->OffsetWindowOrg(0, -m_nGap * m_CharSize.cy);
- pDC->OffsetWindowOrg(0, -GetFixedRowHeight());
- // We need to find out which row to start printing for this page.
- int nTotalRowHeight = 0;
- UINT nNumPages = 1;
- m_nCurrPrintRow = GetFixedRowCount();
- // Not only the row, but we need to figure out column, too
- // Can print 4 pages, where page 1 and 2 represent the same rows but
- // with different WIDE columns.
- //
- // .......
- // .1 .2 . If representing page 3 --> iPageIfIgnoredWideCols = 2
- // ....... iWideColPageOffset = 0
- // .3 .4 . If representing page 2 --> iPageIfIgnoredWideCols = 1
- // ....... iWideColPageOffset = 1
- int iPageIfIgnoredWideCols = pInfo->m_nCurPage / m_nPageMultiplier;
- int iWideColPageOffset = pInfo->m_nCurPage - (iPageIfIgnoredWideCols * m_nPageMultiplier);
- if (iWideColPageOffset > 0)
- iPageIfIgnoredWideCols++;
- if (iWideColPageOffset == 0)
- iWideColPageOffset = m_nPageMultiplier;
- iWideColPageOffset--;
- // calculate current print row based on iPageIfIgnoredWideCols
- while (m_nCurrPrintRow < GetRowCount()
- && (int)nNumPages < iPageIfIgnoredWideCols)
- {
- nTotalRowHeight += GetRowHeight(m_nCurrPrintRow);
- if (nTotalRowHeight > m_nPageHeight) {
- nNumPages++;
- if ((int)nNumPages == iPageIfIgnoredWideCols) break;
- nTotalRowHeight = GetRowHeight(m_nCurrPrintRow);
- }
- m_nCurrPrintRow++;
- }
- m_nPrintColumn = GetFixedColumnCount();
- int iTotalRowWidth = 0;
- int i1, i2;
- // now, calculate which print column to start displaying
- for (i1 = 0; i1 < iWideColPageOffset; i1++)
- {
- for (i2 = m_nPrintColumn; i2 < GetColumnCount(); i2++)
- {
- iTotalRowWidth += GetColumnWidth(i2);
- if (iTotalRowWidth > m_nPageWidth)
- {
- m_nPrintColumn = i2;
- iTotalRowWidth = 0;
- break;
- }
- }
- }
- PrintRowButtons(pDC, pInfo); // print row buttons on each page
- int iColumnOffset = 0;
- for (i1 = 0; i1 < GetFixedColumnCount(); i1++)
- {
- iColumnOffset += GetColumnWidth(i1);
- }
- // Print the column headings
- pInfo->m_rectDraw.bottom = GetFixedRowHeight();
- if (m_nPrintColumn == GetFixedColumnCount())
- {
- // have the column headings fcn draw the upper left fixed cells
- // for the very first columns, only
- pDC->OffsetWindowOrg(0, +GetFixedRowHeight());
- m_nPageWidth += iColumnOffset;
- m_nPrintColumn = 0;
- PrintColumnHeadings(pDC, pInfo);
- m_nPageWidth -= iColumnOffset;
- m_nPrintColumn = GetFixedColumnCount();
- pDC->OffsetWindowOrg(-iColumnOffset, -GetFixedRowHeight());
- }
- else
- {
- // changed all of this here to match above almost exactly same
- pDC->OffsetWindowOrg(0, +GetFixedRowHeight());
- m_nPageWidth += iColumnOffset;
- // print from column 0 ... last column that fits on the current page
- PrintColumnHeadings(pDC, pInfo);
- m_nPageWidth -= iColumnOffset;
- pDC->OffsetWindowOrg(-iColumnOffset, -GetFixedRowHeight());
- }
- if (m_nCurrPrintRow >= GetRowCount()) return;
- // Draw as many rows as will fit on the printed page.
- // Clip the printed page so that there is no partially shown
- // row at the bottom of the page (the same row which will be fully
- // shown at the top of the next page).
- BOOL bFirstPrintedRow = TRUE;
- CRect rect;
- rect.bottom = -1;
- while (m_nCurrPrintRow < GetRowCount())
- {
- rect.top = rect.bottom + 1;
- rect.bottom = rect.top + GetRowHeight(m_nCurrPrintRow) - 1;
- if (rect.bottom > m_nPageHeight) break; // Gone past end of page
- rect.right = -1;
- // modified to allow printing of wide grids on multiple pages
- for (int col = m_nPrintColumn; col < GetColumnCount(); col++)
- {
- rect.left = rect.right + 1;
- rect.right = rect.left
- + GetColumnWidth(col)
- - 1;
- if (rect.right > m_nPageWidth)
- break;
- CGridCellBase* pCell = GetCell(m_nCurrPrintRow, col);
- if (pCell)
- pCell->PrintCell(pDC, m_nCurrPrintRow, col, rect);
- if (m_nGridLines == GVL_BOTH || m_nGridLines == GVL_HORZ)
- {
- int Overlap = (col == 0) ? 0 : 1;
- pDC->MoveTo(rect.left - Overlap, rect.bottom);
- pDC->LineTo(rect.right, rect.bottom);
- if (m_nCurrPrintRow == 0) {
- pDC->MoveTo(rect.left - Overlap, rect.top);
- pDC->LineTo(rect.right, rect.top);
- }
- }
- if (m_nGridLines == GVL_BOTH || m_nGridLines == GVL_VERT)
- {
- int Overlap = (bFirstPrintedRow) ? 0 : 1;
- pDC->MoveTo(rect.right, rect.top - Overlap);
- pDC->LineTo(rect.right, rect.bottom);
- if (col == 0) {
- pDC->MoveTo(rect.left, rect.top - Overlap);
- pDC->LineTo(rect.left, rect.bottom);
- }
- }
- }
- m_nCurrPrintRow++;
- bFirstPrintedRow = FALSE;
- }
- // Footer
- pInfo->m_rectDraw.bottom = m_nFooterHeight * m_CharSize.cy;
- pDC->SetWindowOrg(-m_nLeftMargin * m_CharSize.cx,
- -m_LogicalPageSize.cy + m_nFooterHeight * m_CharSize.cy);
- PrintFooter(pDC, pInfo);
- // SetWindowOrg back for next page
- pDC->SetWindowOrg(0, 0);
- pDC->SelectObject(pOldFont);
- }
- // added by M.Fletcher 12/17/00
- void CGridCtrl::PrintFixedRowCells(int nStartColumn, int nStopColumn, int& row, CRect& rect,
- CDC *pDC, BOOL& bFirst)
- {
- // print all cells from nStartColumn to nStopColumn on row
- for (int col = nStartColumn; col < nStopColumn; col++)
- {
- rect.left = rect.right + 1;
- rect.right = rect.left + GetColumnWidth(col) - 1;
- if (rect.right > m_nPageWidth)
- break;
- CGridCellBase* pCell = GetCell(row, col);
- if (pCell)
- pCell->PrintCell(pDC, row, col, rect);
- if (m_nGridLines == GVL_BOTH || m_nGridLines == GVL_HORZ)
- {
- int Overlap = (col == 0) ? 0 : 1;
- pDC->MoveTo(rect.left - Overlap, rect.bottom);
- pDC->LineTo(rect.right, rect.bottom);
- if (row == 0)
- {
- pDC->MoveTo(rect.left - Overlap, rect.top);
- pDC->LineTo(rect.right, rect.top);
- }
- }
- if (m_nGridLines == GVL_BOTH || m_nGridLines == GVL_VERT)
- {
- int Overlap = (row == 0) ? 0 : 1;
- pDC->MoveTo(rect.right, rect.top - Overlap);
- pDC->LineTo(rect.right, rect.bottom);
- if (bFirst)
- {
- pDC->MoveTo(rect.left - 1, rect.top - Overlap);
- pDC->LineTo(rect.left - 1, rect.bottom);
- bFirst = FALSE;
- }
- }
- } // end of column cells loop
- } // end of CGridCtrl::PrintFixedRowCells
- void CGridCtrl::PrintColumnHeadings(CDC *pDC, CPrintInfo* /*pInfo*/)
- {
- CFont *pOldFont = pDC->SelectObject(&m_PrinterFont);
- CRect rect;
- rect.bottom = -1;
- BOOL bFirst = TRUE;
- BOOL bOriginal;
- // modified to allow column hdr printing of multi-page wide grids
- for (int row = 0; row < GetFixedRowCount(); row++)
- {
- rect.top = rect.bottom + 1;
- rect.bottom = rect.top + GetRowHeight(row) - 1;
- rect.right = -1;
- // if printColumn > fixedcolumncount we are on page 2 or more
- // lets printout those fixed cell headings again the 1 or more that would be missed
- // added by M.Fletcher 12/17/00
- if (m_nPrintColumn >= GetFixedColumnCount())
- {
- bOriginal = bFirst;
- // lets print the missing fixed cells on left first out to last fixed column
- PrintFixedRowCells(0, GetFixedColumnCount(), row, rect, pDC, bFirst);
- bFirst = bOriginal;
- }
- // now back to normal business print cells in heading after all fixed columns
- PrintFixedRowCells(m_nPrintColumn, GetColumnCount(), row, rect, pDC, bFirst);
- } // end of Row Loop
- pDC->SelectObject(pOldFont);
- } // end of CGridCtrl::PrintColumnHeadings
- /*****************************************************************************
- Prints line of row buttons on each page of the printout. Assumes that
- the window origin is setup before calling
- *****************************************************************************/
- void CGridCtrl::PrintRowButtons(CDC *pDC, CPrintInfo* /*pInfo*/)
- {
- CFont *pOldFont = pDC->SelectObject(&m_PrinterFont);
- CRect rect;
- rect.right = -1;
- BOOL bFirst = TRUE;
- for (int iCol = 0; iCol < GetFixedColumnCount(); iCol++)
- {
- rect.left = rect.right + 1;
- rect.right = rect.left
- + GetColumnWidth(iCol)
- - 1;
- rect.bottom = -1;
- for (int iRow = m_nCurrPrintRow; iRow < GetRowCount(); iRow++)
- {
- rect.top = rect.bottom + 1;
- rect.bottom = rect.top + GetRowHeight(iRow) - 1;
- if (rect.bottom > m_nPageHeight)
- break;
- CGridCellBase* pCell = GetCell(iRow, iCol);
- if (pCell)
- pCell->PrintCell(pDC, iRow, iCol, rect);
- if (m_nGridLines == GVL_BOTH || m_nGridLines == GVL_HORZ)
- {
- int Overlap = (iCol == 0) ? 0 : 1;
- pDC->MoveTo(rect.left - Overlap, rect.bottom);
- pDC->LineTo(rect.right, rect.bottom);
- if (bFirst) {
- pDC->MoveTo(rect.left - Overlap, rect.top - 1);
- pDC->LineTo(rect.right, rect.top - 1);
- bFirst = FALSE;
- }
- }
- if (m_nGridLines == GVL_BOTH || m_nGridLines == GVL_VERT)
- {
- int Overlap = (iRow == 0) ? 0 : 1;
- pDC->MoveTo(rect.right, rect.top - Overlap);
- pDC->LineTo(rect.right, rect.bottom);
- if (iCol == 0) {
- pDC->MoveTo(rect.left, rect.top - Overlap);
- pDC->LineTo(rect.left, rect.bottom);
- }
- }
- }
- }
- pDC->SelectObject(pOldFont);
- }
- void CGridCtrl::PrintHeader(CDC *pDC, CPrintInfo *pInfo)
- {
- // print App title on top right margin
- CString strRight;
- strRight.LoadString(AFX_IDS_APP_TITLE);
- // print parent window title in the centre (Gert Rijs)
- CString strCenter;
- CWnd *pParentWnd = GetParent();
- while (pParentWnd)
- {
- pParentWnd->GetWindowText(strCenter);
- if (strCenter.GetLength()) // can happen if it is a CView, CChildFrm has the title
- break;
- pParentWnd = pParentWnd->GetParent();
- }
- CFont BoldFont;
- LOGFONT lf;
- //create bold font for header and footer
- VERIFY(m_PrinterFont.GetLogFont(&lf));
- lf.lfWeight = FW_BOLD;
- VERIFY(BoldFont.CreateFontIndirect(&lf));
- CFont *pNormalFont = pDC->SelectObject(&BoldFont);
- int nPrevBkMode = pDC->SetBkMode(TRANSPARENT);
- CRect rc(pInfo->m_rectDraw);
- if (!strCenter.IsEmpty())
- pDC->DrawText(strCenter, &rc, DT_CENTER | DT_SINGLELINE | DT_NOPREFIX | DT_VCENTER);
- if (!strRight.IsEmpty())
- pDC->DrawText(strRight, &rc, DT_RIGHT | DT_SINGLELINE | DT_NOPREFIX | DT_VCENTER);
- pDC->SetBkMode(nPrevBkMode);
- pDC->SelectObject(pNormalFont);
- BoldFont.DeleteObject();
- // draw ruled-line across top
- pDC->SelectStockObject(BLACK_PEN);
- pDC->MoveTo(rc.left, rc.bottom);
- pDC->LineTo(rc.right, rc.bottom);
- }
- //print footer with a line and date, and page number
- void CGridCtrl::PrintFooter(CDC *pDC, CPrintInfo *pInfo)
- {
- // page numbering on left
- CString strLeft;
- strLeft.Format(_T("Page %d of %d"), pInfo->m_nCurPage, pInfo->GetMaxPage());
- // date and time on the right
- CString strRight;
- COleDateTime t = COleDateTime::GetCurrentTime();
- strRight = t.Format(_T("%c"));
- CRect rc(pInfo->m_rectDraw);
- // draw ruled line on bottom
- pDC->SelectStockObject(BLACK_PEN);
- pDC->MoveTo(rc.left, rc.top);
- pDC->LineTo(rc.right, rc.top);
- CFont BoldFont;
- LOGFONT lf;
- //create bold font for header and footer
- m_PrinterFont.GetLogFont(&lf);
- lf.lfWeight = FW_BOLD;
- BoldFont.CreateFontIndirect(&lf);
- CFont *pNormalFont = pDC->SelectObject(&BoldFont);
- int nPrevBkMode = pDC->SetBkMode(TRANSPARENT);
- // EFW - Bug fix - Force text color to black. It doesn't always
- // get set to a printable color when it gets here.
- pDC->SetTextColor(RGB(0, 0, 0));
- if (!strLeft.IsEmpty())
- pDC->DrawText(strLeft, &rc, DT_LEFT | DT_SINGLELINE | DT_NOPREFIX | DT_VCENTER);
- if (!strRight.IsEmpty())
- pDC->DrawText(strRight, &rc, DT_RIGHT | DT_SINGLELINE | DT_NOPREFIX | DT_VCENTER);
- pDC->SetBkMode(nPrevBkMode);
- pDC->SelectObject(pNormalFont);
- BoldFont.DeleteObject();
- }
- void CGridCtrl::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
- {
- m_PrinterFont.DeleteObject();
- }
- #endif // !defined(_WIN32_WCE_NO_PRINTING) && !defined(GRIDCONTROL_NO_PRINTING)
- #ifndef _WIN32_WCE
- /////////////////////////////////////////////////////////////////////////////
- // CGridCtrl persistance
- BOOL CGridCtrl::Save(LPCTSTR filename, TCHAR chSeparator/*=_T(',')*/)
- {
- CStdioFile File;
- CFileException ex;
- CString strSeparator(chSeparator);
- if (!File.Open(filename, CFile::modeWrite | CFile::modeCreate | CFile::typeText, &ex))
- {
- ex.ReportError();
- return FALSE;
- }
- TRY
- {
- int nNumColumns = GetColumnCount();
- for (int i = 0; i < GetRowCount(); i++)
- {
- for (int j = 0; j < nNumColumns; j++)
- {
- File.WriteString(GetItemText(i, j));
- File.WriteString((j == (nNumColumns - 1)) ? _T("\n") : strSeparator);
- }
- }
- File.Close();
- }
- CATCH(CFileException, e)
- {
- AfxMessageBox(_T("Unable to save grid list"));
- return FALSE;
- }
- END_CATCH
- return TRUE;
- }
- BOOL CGridCtrl::Load(LPCTSTR filename, TCHAR chSeparator/*=_T(',')*/)
- {
- if (GetVirtualMode())
- return FALSE;
- TCHAR *token, *end;
- TCHAR buffer[1024];
- CStdioFile File;
- CFileException ex;
- if (!File.Open(filename, CFile::modeRead | CFile::typeText))
- {
- ex.ReportError();
- return FALSE;
- }
- DeleteAllItems();
- TRY
- {
- // Read Header off file
- File.ReadString(buffer, 1024);
- // Get first token
- for (token = buffer, end = buffer;
- *end && (*end != chSeparator) && (*end != _T('\n'));
- end++)
- ;
- if ((*end == _T('\0')) && (token == end))
- token = NULL;
- *end = _T('\0');
- while (token)
- {
- InsertColumn(token);
- // Get next token
- for (token = ++end; *end && (*end != chSeparator) && (*end != _T('\n'));
- end++)
- ;
- if ((*end == _T('\0')) && (token == end))
- token = NULL;
- *end = _T('\0');
- }
- // Read in rest of data
- int nItem = 0;
- while (File.ReadString(buffer, 1024))
- {
- // Get first token
- for (token = buffer, end = buffer;
- *end && (*end != chSeparator) && (*end != _T('\n')); end++)
- ;
- if ((*end == _T('\0')) && (token == end))
- token = NULL;
- *end = _T('\0');
- int nSubItem = 0;
- while (token)
- {
- if (!nSubItem)
- InsertRow(token);
- else
- SetItemText(nItem, nSubItem, token);
- // Get next token
- for (token = ++end; *end && (*end != chSeparator) && (*end != _T('\n'));
- end++)
- ;
- if ((*end == _T('\0')) && (token == end))
- token = NULL;
- *end = _T('\0');
- nSubItem++;
- }
- nItem++;
- }
- AutoSizeColumns(GetAutoSizeStyle());
- File.Close();
- }
- CATCH(CFileException, e)
- {
- AfxMessageBox(_T("Unable to load grid data"));
- return FALSE;
- }
- END_CATCH
- return TRUE;
- }
- #endif
- /////////////////////////////////////////////////////////////////////////////
- // CGridCtrl overrideables
- #ifndef GRIDCONTROL_NO_DRAGDROP
- // This is no longer needed since I've changed to OLE drag and drop - but it's
- // still cool code. :)
- CImageList* CGridCtrl::CreateDragImage(CPoint *pHotSpot)
- {
- CDC* pDC = GetDC();
- if (!pDC)
- return NULL;
- CRect rect;
- CCellID cell = GetFocusCell();
- if (!GetCellRect(cell.row, cell.col, rect))
- return NULL;
- // Translate coordinate system
- rect.BottomRight() = CPoint(rect.Width(), rect.Height());
- rect.TopLeft() = CPoint(0, 0);
- *pHotSpot = rect.BottomRight();
- // Create a new imagelist (the caller of this function has responsibility
- // for deleting this list)
- CImageList* pList = new CImageList;
- if (!pList || !pList->Create(rect.Width(), rect.Height(), ILC_MASK, 1, 1))
- {
- if (pList)
- delete pList;
- return NULL;
- }
- // Create mem DC and bitmap
- CDC MemDC;
- CBitmap bm;
- MemDC.CreateCompatibleDC(pDC);
- bm.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
- CBitmap* pOldBitmap = MemDC.SelectObject(&bm);
- MemDC.SetWindowOrg(0, 0);
- // Draw cell onto bitmap in memDC
- CGridCellBase* pCell = GetCell(cell.row, cell.col);
- if (pCell)
- pCell->Draw(&MemDC, cell.row, cell.col, rect, FALSE);
- // Clean up
- MemDC.SelectObject(pOldBitmap);
- ReleaseDC(pDC);
- // Add the bitmap we just drew to the image list.
- pList->Add(&bm, GetDefaultCell(FALSE, FALSE)->GetBackClr());
- bm.DeleteObject();
- return pList;
- }
- #endif
- void CGridCtrl::OnFixedRowClick(CCellID& cell)
- {
- if (!IsValid(cell))
- return;
- if (GetHeaderSort())
- {
- //AfxMessageBox("IF");
- CWaitCursor waiter;
- if (cell.col == GetSortColumn())
- SortItems(cell.col, !GetSortAscending());
- else
- SortItems(cell.col, TRUE);
- Invalidate();
- }
- if (GetFixedRowSelection())
- {
- if (cell.col < GetFixedColumnCount())
- {
- m_MouseMode = MOUSE_SELECT_ALL;
- OnSelecting(cell);
- }
- else
- {
- m_MouseMode = MOUSE_SELECT_COL;
- OnSelecting(cell);
- }
- }
- }
- void CGridCtrl::OnFixedColumnClick(CCellID& cell)
- {
- if (!IsValid(cell))
- return;
- // if (m_bListMode && (GetItemState(cell.row, m_nFixedCols) & GVNI_SELECTED))
- // {
- // OnEditCell(cell.row, cell.col, VK_LBUTTON);
- // return;
- // }
- if (GetFixedColumnSelection())
- {
- if (cell.row < GetFixedRowCount())
- {
- m_MouseMode = MOUSE_SELECT_ALL;
- OnSelecting(cell);
- }
- else
- {
- m_MouseMode = MOUSE_SELECT_ROW;
- OnSelecting(cell);
- }
- }
- }
- // Gets the extent of the text pointed to by str (no CDC needed)
- // By default this uses the selected font (which is a bigger font)
- CSize CGridCtrl::GetTextExtent(int nRow, int nCol, LPCTSTR str)
- {
- CGridCellBase* pCell = GetCell(nRow, nCol);
- if (!pCell)
- return CSize(0, 0);
- else
- return pCell->GetTextExtent(str);
- }
- // virtual
- void CGridCtrl::OnEditCell(int nRow, int nCol, CPoint point, UINT nChar)
- {
- #ifndef GRIDCONTROL_NO_TITLETIPS
- m_TitleTip.Hide(); // hide any titletips
- #endif
- // Can we do it?
- CCellID cell(nRow, nCol);
- if (!IsValid(cell) || !IsCellEditable(nRow, nCol))
- return;
- // Can we see what we are doing?
- EnsureVisible(nRow, nCol);
- if (!IsCellVisible(nRow, nCol))
- return;
- // Where, exactly, are we gonna do it??
- CRect rect;
- if (!GetCellRect(cell, rect))
- return;
- // Check we can edit...
- if (SendMessageToParent(nRow, nCol, GVN_BEGINLABELEDIT) >= 0)
- {
- // Let's do it...
- CGridCellBase* pCell = GetCell(nRow, nCol);
- if (pCell)
- pCell->Edit(nRow, nCol, rect, point, IDC_INPLACE_CONTROL, nChar);
- }
- }
- // virtual
- void CGridCtrl::EndEditing()
- {
- CCellID cell = GetFocusCell();
- if (!IsValid(cell)) return;
- CGridCellBase *pCell = GetCell(cell.row, cell.col);
- if (pCell)
- pCell->EndEdit();
- }
- // virtual
- void CGridCtrl::OnEndEditCell(int nRow, int nCol, CString str)
- {
- CString strCurrentText = GetItemText(nRow, nCol);
- if (strCurrentText != str)
- {
- SetItemText(nRow, nCol, str);
- if (ValidateEdit(nRow, nCol, str) &&
- SendMessageToParent(nRow, nCol, GVN_ENDLABELEDIT) >= 0)
- {
- SetModified(TRUE, nRow, nCol);
- RedrawCell(nRow, nCol);
- }
- else
- {
- SetItemText(nRow, nCol, strCurrentText);
- }
- }
- CGridCellBase* pCell = GetCell(nRow, nCol);
- if (pCell)
- pCell->OnEndEdit();
- }
- // If this returns FALSE then the editing isn't allowed
- // virtual
- BOOL CGridCtrl::ValidateEdit(int nRow, int nCol, LPCTSTR str)
- {
- CGridCellBase* pCell = GetCell(nRow, nCol);
- ASSERT(pCell);
- if (!pCell)
- return TRUE;
- return pCell->ValidateEdit(str);
- }
- // virtual
- CString CGridCtrl::GetItemText(int nRow, int nCol) const
- {
- if (nRow < 0 || nRow >= m_nRows || nCol < 0 || nCol >= m_nCols)
- return _T("");
- CGridCellBase* pCell = GetCell(nRow, nCol);
- ASSERT(pCell);
- if (!pCell)
- return _T("");
- return pCell->GetText();
- }
- int CGridCtrl::GetSelCount()
- {
- return m_nArrayListChoose.GetCount();
- }
- int CGridCtrl::GetSelData(int iIndex)
- {
- return m_nArrayListChoose[iIndex];
- }
|