I've just added a tab control to my program. Its mdi, and i want a new tab created/deleted as files are opened/closed. I cant seem to figuers out how this works. My tab control is TCS_OWNERDRAWFIXED, since someone told me thats what it needed to be in my case. I tried looking at TabEdit by Ewayne, but the code is hard to understand, and doesnt really apply to my needs since my program is MDI, does anyone have some example code, or maybe could give me some insight?

Thanks in advance
Posted on 2001-07-22 22:07:07 by karl
This is the code i have used in my Object Creator tool...


; Do A Tab Control1 Box Control...
invoke CreateWindowEx, NULL,
ADDR tabClass, ADDR szObject,
WS_CHILD or WS_VISIBLE or WS_CHILDWINDOW or WS_CLIPSIBLINGS,
TB_X,TB_Y,TB_WD,TB_HT,hWin,TabControl1ID,
hInstance,NULL
mov hTabControl1, eax



; Place Tab Names in the Tab Control 1 and Tab Control 2
mov Tie.imask, TCIF_TEXT or TCIF_IMAGE
mov Tie.iImage, 18
mov Tie.pszText, offset szTab3
invoke SendMessage, hTabControl2, TCM_INSERTITEM, 0, addr Tie

mov Tie.iImage, 13
mov Tie.pszText, offset szTab4
invoke SendMessage, hTabControl2, TCM_INSERTITEM, 1, addr Tie

ifdef _MYDEBUG_ ; --============================ [ DEBUG ] =--
mov Tie.iImage, 10
mov Tie.pszText, offset szDEBUG
invoke SendMessage, hTabControl2, TCM_INSERTITEM, 2, addr Tie
endif ; --==================================================--


Tie is a TC_ITEM structure...


typedef struct _TC_ITEM {
UINT mask; // value specifying which members to retrieve or set
UINT lpReserved1; // reserved; do not use
UINT lpReserved2; // reserved; do not use
LPSTR pszText; // pointer to string containing tab text
int cchTextMax; // size of buffer pointed to by the pszText member
int iImage; // index to tab control's image
LPARAM lParam; // application-defined data associated with tab
} TC_ITEM;


The above inserts a new tab (note the index #'s on insertion (0,1,2) This is the code returned when a tab is selected in the TC_Message......

I havent had a need to remove a Tab yet... but:


TCM_DELETEITEM
wParam = (WPARAM) (int) iItem; // index of the item to delete
lParam = 0; // not used; must be zero


Suggests you need to keep track of these index #'s to remove a tab...

Hope this helps...



:alright:
NaN
Posted on 2001-07-23 00:07:44 by NaN
I cant seem to get it to work, i had that much already. Check it out if you like, or if anyone else wants to, feel free to help :grin:
Thanks
Posted on 2001-07-23 01:32:39 by karl
Also, press New twice (so there are two MDI windows) and the choose tile vertical, and check out how the RichEdit control in the left window doesnt fill the whole window up.. odd, huh?

Thanks all for looking
Posted on 2001-07-23 01:34:38 by karl
That wasnt too hard to lick...


Your Tab problem is due to the fact your using this in your TabWin file:



invoke GetClientRect,hwndFrame,addr Rct
invoke CreateWindowEx,NULL,addr tabClass,NULL,\
WS_CHILD or WS_VISIBLE or WS_CHILDWINDOW or WS_CLIPSIBLINGS,
0,0,Rct.right,20,hParent,702,hInstance,NULL
mov hTabWin,eax


More specifically, the hwndFrame, which is the initial handle given on creation of your window. Dont ask me why, but i have since learned that you should always take the most recient handle given... in this case it would be the more recient hParent that you use to create the tab itself. Long story short, you have 2 handles to the same window, only one is Old and out of date (if you will), and the other is current (since it gets passed into the message loop).

I simply changed the:

invoke GetClientRect,hwndFrame,addr Rct

To

invoke GetClientRect, hParent, addr Rct

And it was away to the races... :)

As for you Edit thingy... well its toooooo humid to continue tonight.. but if your sizing your controls in a simular way, then such problems may be expected...

Happy Coding..

:alright:
NaN
Posted on 2001-07-23 22:38:35 by NaN
I felt i was being lazy with my last comment about the humidity, so i decieded to give it look over anyways...

I have got your other problem cornered now...

The problem is hard to see, untill you realize what is going on.. :)

You have a "ChildProc" which by class definition is to handle EVERY Mdi Child created (this is fine), and in the WM_CREATE portion you create a Richedit control for every MDI child... This is also fine, but the problem is this: Every new control created is assigned to the same global handle in your .data --> hRiched

So the hRiched handle only keeps track of the most currently created richedit control. So when along comes the WM_SIZE message to any given MDI child, your code looked up this handle and adjusts it.. mean while the window in view, is "Physically" adjusted, while the Riched control on a MDI in the background (out of site) is actually recieving the new Richedit positions..

This leaves you with the one in front having the same control size.. and "seemingly" the control hiden from view never changed.... (tricky to find)...

This also explains why one ONE of the controls will adjust properly, no matter how many MDI's you make... Again, since your only keeping the handle to ONE richedit control....

The solution is also quite simpe.... Make use of the Set/Get WindowLong...


ChildProc proc hChild:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
LOCAL Rct:RECT
LOCAL tbb:TBBUTTON
LOCAL TEMP :DWORD
.if uMsg==WM_CREATE
invoke GetClientRect, hChild, addr Rct

; create richedit in the childwin
invoke CreateWindowEx,WS_EX_CLIENTEDGE,addr RichEditClass,0,\
WS_CHILD or WS_VISIBLE or ES_MULTILINE or \
WS_VSCROLL or WS_HSCROLL or ES_NOHIDESEL,\
0, 0, Rct.right, Rct.bottom,\
;CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,\
hChild,RichEditID,hInstance,0
mov TEMP,eax
invoke SetWindowLong, hChild, GWL_USERDATA, TEMP

invoke SendMessage,TEMP,EM_LIMITTEXT,-1,0
invoke SendMessage,TEMP,EM_SETMODIFY,FALSE,0
invoke SendMessage,TEMP,EM_EMPTYUNDOBUFFER,0,0
; create a button on the button bar with the filename in it


And in the WM_SIZE:


.elseif uMsg==WM_SIZE
invoke GetWindowLong, hChild, GWL_USERDATA
mov TEMP, eax
invoke GetClientRect,hChild,addr Rct
invoke MoveWindow,TEMP,0,0,Rct.right,Rct.bottom,TRUE
invoke DefMDIChildProc,hChild,uMsg,wParam,lParam


Again.. there is no real change here, i just added a TEMP variable to the proc and used it instead of hRiched.... (you can ignore the GetClientRect stuff if you want.. there is not problem there.. it was just my debuggin leftovers... :) )

Anywho... Happy coding...

:alright:
NaN .. and its not even Christmas... heheh
Posted on 2001-07-23 23:26:34 by NaN
NaN, thanks SOOO much, you are the man for helping me realize my foolish mistakes! :alright: Anyway, I apreciate this very much, you will not be forgotten :grin:
Posted on 2001-07-24 19:37:44 by karl
Glad to help... good luck with your work..

:alright:
NaN
Posted on 2001-07-24 21:38:35 by NaN
NaN,

Since I created my richedit controls as a local tmp, how do I send messages to the windows? (or really just the current one, since its for a function that prints the col/row to the status bat that needs to send a message to the richedit control)

Thanks again NaN :grin:
Posted on 2001-07-25 03:28:14 by karl
Duh, sorry, GetWindowLong.. I'm very, very tired. lol

Karl :alright:
Posted on 2001-07-25 03:34:33 by karl