Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
8ee3144a
Commit
8ee3144a
authored
May 09, 2000
by
Aric Stewart
Committed by
Alexandre Julliard
May 09, 2000
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added the ability to use multiline tab controls to wine.
parent
b7ed6df2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
220 additions
and
49 deletions
+220
-49
tab.c
dlls/comctl32/tab.c
+215
-48
tab.h
include/tab.h
+5
-1
No files found.
dlls/comctl32/tab.c
View file @
8ee3144a
...
...
@@ -174,14 +174,15 @@ static BOOL TAB_InternalGetItemRect(
RECT
*
itemRect
,
RECT
*
selectedRect
)
{
RECT
tmpItemRect
;
RECT
tmpItemRect
,
clientRect
;
LONG
lStyle
=
GetWindowLongA
(
hwnd
,
GWL_STYLE
);
/*
* Perform a sanity check and a trivial visibility check.
*/
if
(
(
infoPtr
->
uNumItem
<=
0
)
||
(
itemIndex
>=
infoPtr
->
uNumItem
)
||
(
itemIndex
<
infoPtr
->
leftmostVisible
)
)
(
!
(
lStyle
&
TCS_MULTILINE
)
&&
(
itemIndex
<
infoPtr
->
leftmostVisible
)
)
)
return
FALSE
;
/*
...
...
@@ -197,6 +198,31 @@ static BOOL TAB_InternalGetItemRect(
*
itemRect
=
infoPtr
->
items
[
itemIndex
].
rect
;
/*
* calculate the times bottom and top based on the row
*/
GetClientRect
(
hwnd
,
&
clientRect
);
if
(
lStyle
&
TCS_BOTTOM
)
{
itemRect
->
bottom
=
clientRect
.
bottom
-
SELECTED_TAB_OFFSET
-
itemRect
->
top
*
(
infoPtr
->
tabHeight
-
2
);
itemRect
->
top
=
clientRect
.
bottom
-
infoPtr
->
tabHeight
-
itemRect
->
top
*
(
infoPtr
->
tabHeight
-
2
);
}
else
{
itemRect
->
bottom
=
clientRect
.
top
+
infoPtr
->
tabHeight
+
itemRect
->
top
*
(
infoPtr
->
tabHeight
-
2
);
itemRect
->
top
=
clientRect
.
top
+
SELECTED_TAB_OFFSET
+
itemRect
->
top
*
(
infoPtr
->
tabHeight
-
2
);
}
/*
* "scroll" it to make sure the item at the very left of the
* tab control is the leftmost visible tab.
*/
...
...
@@ -463,9 +489,9 @@ static LRESULT TAB_AdjustRect(
* Add the height of the tabs.
*/
if
(
GetWindowLongA
(
hwnd
,
GWL_STYLE
)
&
TCS_BOTTOM
)
prc
->
bottom
+=
infoPtr
->
tabHeight
;
prc
->
bottom
+=
(
infoPtr
->
tabHeight
-
2
)
*
(
infoPtr
->
uNumRows
+
1
)
+
2
;
else
prc
->
top
-=
infoPtr
->
tabHeight
;
prc
->
top
-=
(
infoPtr
->
tabHeight
-
2
)
*
(
infoPtr
->
uNumRows
+
1
)
+
2
;
/*
* Inflate the rectangle for the padding
...
...
@@ -497,9 +523,9 @@ static LRESULT TAB_AdjustRect(
* Remove the height of the tabs.
*/
if
(
GetWindowLongA
(
hwnd
,
GWL_STYLE
)
&
TCS_BOTTOM
)
prc
->
bottom
-=
infoPtr
->
tabHeight
;
prc
->
bottom
-=
(
infoPtr
->
tabHeight
-
2
)
*
(
infoPtr
->
uNumRows
+
1
)
+
2
;
else
prc
->
top
+=
infoPtr
->
tabHeight
;
prc
->
top
+=
(
infoPtr
->
tabHeight
-
2
)
*
(
infoPtr
->
uNumRows
+
1
)
+
2
;
}
...
...
@@ -575,10 +601,6 @@ static void TAB_SetupScrolling(
*/
if
(
infoPtr
->
hwndUpDown
==
0
)
{
/*
* I use a scrollbar since it seems to be more stable than the Updown
* control.
*/
infoPtr
->
hwndUpDown
=
CreateWindowA
(
"msctls_updown32"
,
""
,
WS_VISIBLE
|
WS_CHILD
|
UDS_HORZ
,
...
...
@@ -651,6 +673,7 @@ static void TAB_SetItemBounds (HWND hwnd)
TEXTMETRICA
fontMetrics
;
INT
curItem
;
INT
curItemLeftPos
;
INT
curItemRowCount
;
HFONT
hFont
,
hOldFont
;
HDC
hdc
;
RECT
clientRect
;
...
...
@@ -675,6 +698,7 @@ static void TAB_SetItemBounds (HWND hwnd)
* The leftmost item will be "0" aligned
*/
curItemLeftPos
=
0
;
curItemRowCount
=
0
;
if
(
!
(
lStyle
&
TCS_FIXEDWIDTH
)
&&
!
((
lStyle
&
TCS_OWNERDRAWFIXED
)
&&
infoPtr
->
fSizeSet
)
)
{
...
...
@@ -711,24 +735,6 @@ static void TAB_SetItemBounds (HWND hwnd)
for
(
curItem
=
0
;
curItem
<
infoPtr
->
uNumItem
;
curItem
++
)
{
/*
* Calculate the vertical position of the tab
*/
if
(
lStyle
&
TCS_BOTTOM
)
{
infoPtr
->
items
[
curItem
].
rect
.
bottom
=
clientRect
.
bottom
-
SELECTED_TAB_OFFSET
;
infoPtr
->
items
[
curItem
].
rect
.
top
=
clientRect
.
bottom
-
infoPtr
->
tabHeight
;
}
else
{
infoPtr
->
items
[
curItem
].
rect
.
top
=
clientRect
.
top
+
SELECTED_TAB_OFFSET
;
infoPtr
->
items
[
curItem
].
rect
.
bottom
=
clientRect
.
top
+
infoPtr
->
tabHeight
;
}
/*
* Set the leftmost position of the tab.
*/
infoPtr
->
items
[
curItem
].
rect
.
left
=
curItemLeftPos
;
...
...
@@ -764,6 +770,27 @@ static void TAB_SetItemBounds (HWND hwnd)
num
*
HORIZONTAL_ITEM_PADDING
;
}
/*
* Check if this is a multiline tab control and if so
* check to see if we should wrap the tabs
*
* Because we are going to arange all these tabs evenly
* really we are basically just counting rows at this point
*
*/
if
((
lStyle
&
TCS_MULTILINE
)
&&
(
infoPtr
->
items
[
curItem
].
rect
.
right
>
clientRect
.
right
))
{
infoPtr
->
items
[
curItem
].
rect
.
right
-=
infoPtr
->
items
[
curItem
].
rect
.
left
;
infoPtr
->
items
[
curItem
].
rect
.
left
=
0
;
curItemRowCount
++
;
}
infoPtr
->
items
[
curItem
].
rect
.
bottom
=
0
;
infoPtr
->
items
[
curItem
].
rect
.
top
=
curItemRowCount
;
TRACE
(
"TextSize: %i
\n
"
,
size
.
cx
);
TRACE
(
"Rect: T %i, L %i, B %i, R %i
\n
"
,
infoPtr
->
items
[
curItem
].
rect
.
top
,
...
...
@@ -776,23 +803,118 @@ static void TAB_SetItemBounds (HWND hwnd)
* of this one.
*/
if
(
lStyle
&
TCS_BUTTONS
)
curItemLeftPos
=
infoPtr
->
items
[
curItem
].
rect
.
right
+
BUTTON_SPACINGX
;
curItemLeftPos
=
infoPtr
->
items
[
curItem
].
rect
.
right
+
BUTTON_SPACINGX
;
else
curItemLeftPos
=
infoPtr
->
items
[
curItem
].
rect
.
right
;
}
if
(
!
(
lStyle
&
TCS_MULTILINE
))
{
/*
* Check if we need a scrolling control.
*/
infoPtr
->
needsScrolling
=
(
curItemLeftPos
+
(
2
*
SELECTED_TAB_OFFSET
)
>
clientRect
.
right
);
TAB_SetupScrolling
(
hwnd
,
infoPtr
,
&
clientRect
);
}
/*
*
Check if we need a scrolling control.
*
Set the number of rows
*/
infoPtr
->
needsScrolling
=
(
curItemLeftPos
+
(
2
*
SELECTED_TAB_OFFSET
)
>
clientRect
.
right
);
/* Don't need scrolling, then update infoPtr->leftmostVisible */
if
(
!
infoPtr
->
needsScrolling
)
infoPtr
->
leftmostVisible
=
0
;
infoPtr
->
uNumRows
=
curItemRowCount
;
TAB_SetupScrolling
(
hwnd
,
infoPtr
,
&
clientRect
);
if
((
lStyle
&
TCS_MULTILINE
)
&&
(
infoPtr
->
uNumItem
>
0
))
{
INT
widthDiff
,
remainder
;
INT
tabPerRow
,
remTab
;
INT
iRow
,
iItm
;
INT
iIndexStart
=
0
,
iIndexEnd
=
0
,
iCount
=
0
;
/*
* Ok Microsoft trys to even out the rows. place the same
* number of tabs in each row. So lets give that a shot
*
*/
tabPerRow
=
infoPtr
->
uNumItem
/
(
infoPtr
->
uNumRows
+
1
);
remTab
=
infoPtr
->
uNumItem
%
(
infoPtr
->
uNumRows
+
1
);
for
(
iItm
=
0
,
iRow
=
0
,
iCount
=
0
,
curItemLeftPos
=
0
;
iItm
<
infoPtr
->
uNumItem
;
iItm
++
,
iCount
++
)
{
if
(
iCount
>=
((
iRow
<
remTab
)
?
tabPerRow
+
1
:
tabPerRow
))
{
iRow
++
;
curItemLeftPos
=
0
;
iCount
=
0
;
}
/*
* normalize the current rect
*/
infoPtr
->
items
[
iItm
].
rect
.
right
-=
infoPtr
->
items
[
iItm
].
rect
.
left
;
infoPtr
->
items
[
iItm
].
rect
.
left
=
0
;
infoPtr
->
items
[
iItm
].
rect
.
top
=
iRow
;
infoPtr
->
items
[
iItm
].
rect
.
left
+=
curItemLeftPos
;
infoPtr
->
items
[
iItm
].
rect
.
right
+=
curItemLeftPos
;
if
(
lStyle
&
TCS_BUTTONS
)
curItemLeftPos
=
infoPtr
->
items
[
iItm
].
rect
.
right
+
BUTTON_SPACINGX
;
else
curItemLeftPos
=
infoPtr
->
items
[
iItm
].
rect
.
right
;
}
/*
* Justify the rows
*
*/
{
while
(
iIndexStart
<
infoPtr
->
uNumItem
)
{
/*
* find the indexs of the row
*/
for
(
iIndexEnd
=
iIndexStart
;
(
iIndexEnd
<
infoPtr
->
uNumItem
)
&&
(
infoPtr
->
items
[
iIndexEnd
].
rect
.
top
==
infoPtr
->
items
[
iIndexStart
].
rect
.
top
)
;
iIndexEnd
++
)
/* intentionaly blank */
;
/*
* we need to justify these tabs so they fill the whole given
* client area
*
*/
widthDiff
=
clientRect
.
right
-
(
2
*
SELECTED_TAB_OFFSET
)
-
infoPtr
->
items
[
iIndexEnd
-
1
].
rect
.
right
;
iCount
=
iIndexEnd
-
iIndexStart
;
if
(
iCount
)
{
INT
iIndex
;
remainder
=
widthDiff
%
iCount
;
widthDiff
=
widthDiff
/
iCount
;
for
(
iIndex
=
iIndexStart
,
iCount
=
0
;
iIndex
<
iIndexEnd
;
iIndex
++
,
iCount
++
)
{
infoPtr
->
items
[
iIndex
].
rect
.
left
+=
iCount
*
widthDiff
;
infoPtr
->
items
[
iIndex
].
rect
.
right
+=
(
iCount
+
1
)
*
widthDiff
;
}
infoPtr
->
items
[
iIndex
-
1
].
rect
.
right
+=
remainder
;
}
iIndexStart
=
iIndexEnd
;
}
}
}
TAB_EnsureSelectionVisible
(
hwnd
,
infoPtr
);
/*
* Cleanup
*/
...
...
@@ -1044,7 +1166,14 @@ static void TAB_DrawItem(
/*
* Draw the text;
*/
DrawTextA
(
hdc
,
if
(
lStyle
&
TCS_RIGHTJUSTIFY
)
DrawTextA
(
hdc
,
infoPtr
->
items
[
iItem
].
pszText
,
lstrlenA
(
infoPtr
->
items
[
iItem
].
pszText
),
&
r
,
DT_CENTER
|
DT_SINGLELINE
|
DT_VCENTER
);
else
DrawTextA
(
hdc
,
infoPtr
->
items
[
iItem
].
pszText
,
lstrlenA
(
infoPtr
->
items
[
iItem
].
pszText
),
&
r
,
...
...
@@ -1101,11 +1230,11 @@ static void TAB_DrawBorder (HWND hwnd, HDC hdc)
*/
if
(
GetWindowLongA
(
hwnd
,
GWL_STYLE
)
&
TCS_BOTTOM
)
{
rect
.
bottom
-=
infoPtr
->
tabHeight
;
rect
.
bottom
-=
(
infoPtr
->
tabHeight
-
2
)
*
(
infoPtr
->
uNumRows
+
1
)
+
2
;
}
else
{
rect
.
top
+=
infoPtr
->
tabHeight
;
rect
.
top
+=
(
infoPtr
->
tabHeight
-
2
)
*
(
infoPtr
->
uNumRows
+
1
)
+
2
;
}
/*
...
...
@@ -1180,13 +1309,13 @@ static void TAB_Refresh (HWND hwnd, HDC hdc)
* Then, draw the selected item
*/
TAB_DrawItem
(
hwnd
,
hdc
,
infoPtr
->
iSelected
);
/*
* If we haven't set the current focus yet, set it now.
* Only happens when we first paint the tab controls.
*/
if
(
infoPtr
->
uFocus
==
-
1
)
TAB_SetCurFocus
(
hwnd
,
infoPtr
->
iSelected
);
if
(
infoPtr
->
uFocus
==
-
1
)
TAB_SetCurFocus
(
hwnd
,
infoPtr
->
iSelected
);
}
SelectObject
(
hdc
,
hOldFont
);
...
...
@@ -1236,6 +1365,41 @@ static void TAB_EnsureSelectionVisible(
{
INT
iSelected
=
infoPtr
->
iSelected
;
/*
* set the items row to the bottommost row or topmost row depending on
* style
*/
if
(
infoPtr
->
uNumRows
>
0
)
{
INT
newselected
=
infoPtr
->
items
[
iSelected
].
rect
.
top
;
INT
iTargetRow
;
LONG
lStyle
=
GetWindowLongA
(
hwnd
,
GWL_STYLE
);
if
(
lStyle
&
TCS_BOTTOM
)
iTargetRow
=
0
;
else
iTargetRow
=
infoPtr
->
uNumRows
;
if
(
newselected
!=
iTargetRow
)
{
INT
i
;
for
(
i
=
0
;
i
<
infoPtr
->
uNumItem
;
i
++
)
if
(
infoPtr
->
items
[
i
].
rect
.
top
==
newselected
)
infoPtr
->
items
[
i
].
rect
.
top
=
iTargetRow
;
else
if
(
lStyle
&
TCS_BOTTOM
)
{
if
(
infoPtr
->
items
[
i
].
rect
.
top
<
newselected
)
infoPtr
->
items
[
i
].
rect
.
top
+=
1
;
}
else
{
if
(
infoPtr
->
items
[
i
].
rect
.
top
>
newselected
)
infoPtr
->
items
[
i
].
rect
.
top
-=
1
;
}
}
}
/*
* Do the trivial cases first.
*/
...
...
@@ -1301,11 +1465,13 @@ static void TAB_InvalidateTabArea(
if
(
GetWindowLongA
(
hwnd
,
GWL_STYLE
)
&
TCS_BOTTOM
)
{
clientRect
.
top
=
clientRect
.
bottom
-
(
infoPtr
->
tabHeight
+
3
);
clientRect
.
top
=
clientRect
.
bottom
-
(
infoPtr
->
tabHeight
*
(
infoPtr
->
uNumRows
+
1
)
+
3
);
}
else
{
clientRect
.
bottom
=
clientRect
.
top
+
(
infoPtr
->
tabHeight
+
1
);
clientRect
.
bottom
=
clientRect
.
top
+
(
infoPtr
->
tabHeight
*
(
infoPtr
->
uNumRows
+
1
)
+
1
);
}
InvalidateRect
(
hwnd
,
&
clientRect
,
TRUE
);
...
...
@@ -1389,12 +1555,12 @@ TAB_InsertItem (HWND hwnd, WPARAM wParam, LPARAM lParam)
if
(
pti
->
mask
&
TCIF_PARAM
)
infoPtr
->
items
[
iItem
].
lParam
=
pti
->
lParam
;
TAB_SetItemBounds
(
hwnd
);
TAB_InvalidateTabArea
(
hwnd
,
infoPtr
);
TRACE
(
"[%04x]: added item %d '%s'
\n
"
,
hwnd
,
iItem
,
infoPtr
->
items
[
iItem
].
pszText
);
TAB_SetItemBounds
(
hwnd
);
return
iItem
;
}
...
...
@@ -1668,6 +1834,7 @@ TAB_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
SetWindowLongA
(
hwnd
,
0
,
(
DWORD
)
infoPtr
);
infoPtr
->
uNumItem
=
0
;
infoPtr
->
uNumRows
=
0
;
infoPtr
->
hFont
=
0
;
infoPtr
->
items
=
0
;
infoPtr
->
hcurArrow
=
LoadCursorA
(
0
,
IDC_ARROWA
);
...
...
@@ -1938,7 +2105,7 @@ TAB_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
default:
if
(
uMsg
>=
WM_USER
)
WARN
(
"unknown msg %04x wp=%08x lp=%08lx
\n
"
,
ERR
(
"unknown msg %04x wp=%08x lp=%08lx
\n
"
,
uMsg
,
wParam
,
lParam
);
return
DefWindowProcA
(
hwnd
,
uMsg
,
wParam
,
lParam
);
}
...
...
include/tab.h
View file @
8ee3144a
...
...
@@ -20,12 +20,16 @@ typedef struct tagTAB_ITEM
LPARAM
lParam
;
RECT
rect
;
/* bounding rectangle of the item relative to the
* leftmost item (the leftmost item, 0, would have a
* "left" member of 0 in this rectangle) */
* "left" member of 0 in this rectangle)
*
* additionally the top member hold the row number
* and bottom is unused and should be 0 */
}
TAB_ITEM
;
typedef
struct
tagTAB_INFO
{
UINT
uNumItem
;
/* number of tab items */
UINT
uNumRows
;
/* number of tab rows */
INT
tabHeight
;
/* height of the tab row */
INT
tabWidth
;
/* width of tabs */
HFONT
hFont
;
/* handle to the current font */
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment