Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
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-winehq
Commits
5b06498b
Commit
5b06498b
authored
Jun 11, 2017
by
Fabian Maurer
Committed by
Alexandre Julliard
Jun 12, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
comctl32/taskdialog: Added support for custom buttons.
Signed-off-by:
Nikolay Sivov
<
nsivov@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
df07533a
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
192 additions
and
57 deletions
+192
-57
taskdialog.c
dlls/comctl32/taskdialog.c
+192
-57
No files found.
dlls/comctl32/taskdialog.c
View file @
5b06498b
...
...
@@ -20,6 +20,7 @@
*/
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#define NONAMELESSUNION
...
...
@@ -43,7 +44,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(taskdialog);
#define ALIGN_LENGTH(_Len, _Align) _Len = ALIGNED_LENGTH(_Len, _Align)
#define ALIGN_POINTER(_Ptr, _Align) _Ptr = ALIGNED_POINTER(_Ptr, _Align)
static
const
UINT
DIALOG_MIN_WIDTH
=
18
0
;
static
const
UINT
DIALOG_MIN_WIDTH
=
24
0
;
static
const
UINT
DIALOG_SPACING
=
5
;
static
const
UINT
DIALOG_BUTTON_WIDTH
=
50
;
static
const
UINT
DIALOG_BUTTON_HEIGHT
=
14
;
...
...
@@ -70,6 +71,15 @@ struct taskdialog_template_desc
HFONT
font
;
};
struct
taskdialog_button_desc
{
int
id
;
const
WCHAR
*
text
;
unsigned
int
width
;
unsigned
int
line
;
HINSTANCE
hinst
;
};
static
void
pixels_to_dialogunits
(
const
struct
taskdialog_template_desc
*
desc
,
LONG
*
width
,
LONG
*
height
)
{
if
(
width
)
...
...
@@ -92,6 +102,47 @@ static void template_write_data(char **ptr, const void *src, unsigned int size)
*
ptr
+=
size
;
}
/* used to calculate size for the controls */
static
void
taskdialog_get_text_extent
(
const
struct
taskdialog_template_desc
*
desc
,
const
WCHAR
*
text
,
BOOL
user_resource
,
SIZE
*
sz
)
{
RECT
rect
=
{
0
,
0
,
desc
->
dialog_width
-
DIALOG_SPACING
*
2
,
0
};
/* padding left and right of the control */
const
WCHAR
*
textW
=
NULL
;
static
const
WCHAR
nulW
;
unsigned
int
length
;
HFONT
oldfont
;
HDC
hdc
;
if
(
IS_INTRESOURCE
(
text
))
{
if
(
!
(
length
=
LoadStringW
(
user_resource
?
desc
->
taskconfig
->
hInstance
:
COMCTL32_hModule
,
(
UINT_PTR
)
text
,
(
WCHAR
*
)
&
textW
,
0
)))
{
WARN
(
"Failed to load text
\n
"
);
textW
=
&
nulW
;
length
=
0
;
}
}
else
{
textW
=
text
;
length
=
strlenW
(
textW
);
}
hdc
=
GetDC
(
0
);
oldfont
=
SelectObject
(
hdc
,
desc
->
font
);
dialogunits_to_pixels
(
desc
,
&
rect
.
right
,
NULL
);
DrawTextW
(
hdc
,
textW
,
length
,
&
rect
,
DT_LEFT
|
DT_EXPANDTABS
|
DT_CALCRECT
|
DT_WORDBREAK
);
pixels_to_dialogunits
(
desc
,
&
rect
.
right
,
&
rect
.
bottom
);
SelectObject
(
hdc
,
oldfont
);
ReleaseDC
(
0
,
hdc
);
sz
->
cx
=
rect
.
right
-
rect
.
left
;
sz
->
cy
=
rect
.
bottom
-
rect
.
top
;
}
static
unsigned
int
taskdialog_add_control
(
struct
taskdialog_template_desc
*
desc
,
WORD
id
,
const
WCHAR
*
class
,
HINSTANCE
hInstance
,
const
WCHAR
*
text
,
short
x
,
short
y
,
short
cx
,
short
cy
)
{
...
...
@@ -139,43 +190,18 @@ static unsigned int taskdialog_add_control(struct taskdialog_template_desc *desc
static
unsigned
int
taskdialog_add_static_label
(
struct
taskdialog_template_desc
*
desc
,
WORD
id
,
const
WCHAR
*
str
)
{
RECT
rect
=
{
0
,
0
,
desc
->
dialog_width
-
DIALOG_SPACING
*
2
,
0
};
/* padding left and right of the control */
const
WCHAR
*
textW
=
NULL
;
unsigned
int
size
,
length
;
HFONT
oldfont
;
HDC
hdc
;
unsigned
int
size
;
SIZE
sz
;
if
(
!
str
)
return
0
;
if
(
IS_INTRESOURCE
(
str
))
{
if
(
!
(
length
=
LoadStringW
(
desc
->
taskconfig
->
hInstance
,
(
UINT_PTR
)
str
,
(
WCHAR
*
)
&
textW
,
0
)))
{
WARN
(
"Failed to load static text %s, id %#x
\n
"
,
debugstr_w
(
str
),
id
);
return
0
;
}
}
else
{
textW
=
str
;
length
=
strlenW
(
textW
);
}
hdc
=
GetDC
(
0
);
oldfont
=
SelectObject
(
hdc
,
desc
->
font
);
dialogunits_to_pixels
(
desc
,
&
rect
.
right
,
NULL
);
DrawTextW
(
hdc
,
textW
,
length
,
&
rect
,
DT_LEFT
|
DT_EXPANDTABS
|
DT_CALCRECT
|
DT_WORDBREAK
);
pixels_to_dialogunits
(
desc
,
&
rect
.
right
,
&
rect
.
bottom
);
SelectObject
(
hdc
,
oldfont
);
ReleaseDC
(
0
,
hdc
);
taskdialog_get_text_extent
(
desc
,
str
,
TRUE
,
&
sz
);
desc
->
dialog_height
+=
DIALOG_SPACING
;
size
=
taskdialog_add_control
(
desc
,
id
,
WC_STATICW
,
desc
->
taskconfig
->
hInstance
,
str
,
DIALOG_SPACING
,
desc
->
dialog_height
,
rect
.
right
,
rect
.
bottom
);
desc
->
dialog_height
+=
rect
.
bottom
;
desc
->
dialog_height
,
sz
.
cx
,
sz
.
cy
);
desc
->
dialog_height
+=
sz
.
cy
+
DIALOG_SPACING
;
return
size
;
}
...
...
@@ -189,37 +215,146 @@ static unsigned int taskdialog_add_content(struct taskdialog_template_desc *desc
return
taskdialog_add_static_label
(
desc
,
ID_CONTENT
,
desc
->
taskconfig
->
pszContent
);
}
static
unsigned
int
taskdialog_add_common_buttons
(
struct
taskdialog_template_desc
*
desc
)
static
void
taskdialog_init_button
(
struct
taskdialog_button_desc
*
button
,
struct
taskdialog_template_desc
*
desc
,
int
id
,
const
WCHAR
*
text
,
BOOL
custom_button
)
{
SIZE
sz
;
taskdialog_get_text_extent
(
desc
,
text
,
custom_button
,
&
sz
);
button
->
id
=
id
;
button
->
text
=
text
;
button
->
width
=
max
(
DIALOG_BUTTON_WIDTH
,
sz
.
cx
+
DIALOG_SPACING
*
2
);
button
->
line
=
0
;
button
->
hinst
=
custom_button
?
desc
->
taskconfig
->
hInstance
:
COMCTL32_hModule
;
}
static
void
taskdialog_init_common_buttons
(
struct
taskdialog_template_desc
*
desc
,
struct
taskdialog_button_desc
*
buttons
,
unsigned
int
*
button_count
)
{
short
button_x
=
desc
->
dialog_width
-
DIALOG_BUTTON_WIDTH
-
DIALOG_SPACING
;
DWORD
flags
=
desc
->
taskconfig
->
dwCommonButtons
;
unsigned
int
size
=
0
;
#define TASKDIALOG_
ADD
_COMMON_BUTTON(id) \
#define TASKDIALOG_
INIT
_COMMON_BUTTON(id) \
do { \
size += taskdialog_add_control(desc, ID##id, WC_BUTTONW, COMCTL32_hModule, MAKEINTRESOURCEW(IDS_BUTTON_##id), \
button_x, desc->dialog_height + DIALOG_SPACING, DIALOG_BUTTON_WIDTH, DIALOG_BUTTON_HEIGHT); \
button_x -= DIALOG_BUTTON_WIDTH + DIALOG_SPACING; \
taskdialog_init_button(&buttons[(*button_count)++], desc, ID##id, MAKEINTRESOURCEW(IDS_BUTTON_##id), FALSE); \
} while(0)
if
(
flags
&
TDCBF_CLOSE_BUTTON
)
TASKDIALOG_ADD_COMMON_BUTTON
(
CLOSE
);
if
(
flags
&
TDCBF_CANCEL_BUTTON
)
TASKDIALOG_ADD_COMMON_BUTTON
(
CANCEL
);
if
(
flags
&
TDCBF_RETRY_BUTTON
)
TASKDIALOG_ADD_COMMON_BUTTON
(
RETRY
);
if
(
flags
&
TDCBF_NO_BUTTON
)
TASKDIALOG_ADD_COMMON_BUTTON
(
NO
);
if
(
flags
&
TDCBF_YES_BUTTON
)
TASKDIALOG_ADD_COMMON_BUTTON
(
YES
);
if
(
flags
&
TDCBF_OK_BUTTON
)
TASKDIALOG_ADD_COMMON_BUTTON
(
OK
);
/* Always add OK button */
if
(
list_empty
(
&
desc
->
controls
))
TASKDIALOG_ADD_COMMON_BUTTON
(
OK
);
#undef TASKDIALOG_ADD_COMMON_BUTTON
/* make room for common buttons row */
desc
->
dialog_height
+=
DIALOG_BUTTON_HEIGHT
+
2
*
DIALOG_SPACING
;
TASKDIALOG_INIT_COMMON_BUTTON
(
OK
);
if
(
flags
&
TDCBF_YES_BUTTON
)
TASKDIALOG_INIT_COMMON_BUTTON
(
YES
);
if
(
flags
&
TDCBF_NO_BUTTON
)
TASKDIALOG_INIT_COMMON_BUTTON
(
NO
);
if
(
flags
&
TDCBF_RETRY_BUTTON
)
TASKDIALOG_INIT_COMMON_BUTTON
(
RETRY
);
if
(
flags
&
TDCBF_CANCEL_BUTTON
)
TASKDIALOG_INIT_COMMON_BUTTON
(
CANCEL
);
if
(
flags
&
TDCBF_CLOSE_BUTTON
)
TASKDIALOG_INIT_COMMON_BUTTON
(
CLOSE
);
#undef TASKDIALOG_INIT_COMMON_BUTTON
}
static
unsigned
int
taskdialog_add_buttons
(
struct
taskdialog_template_desc
*
desc
)
{
unsigned
int
count
=
0
,
buttons_size
,
i
,
line_count
,
size
=
0
;
unsigned
int
location_x
,
*
line_widths
,
alignment
=
~
0u
;
const
TASKDIALOGCONFIG
*
taskconfig
=
desc
->
taskconfig
;
struct
taskdialog_button_desc
*
buttons
;
/* Allocate enough memory for the custom and the default buttons. Maximum 6 default buttons possible. */
buttons_size
=
6
;
if
(
taskconfig
->
cButtons
&&
taskconfig
->
pButtons
)
buttons_size
+=
taskconfig
->
cButtons
;
if
(
!
(
buttons
=
Alloc
(
buttons_size
*
sizeof
(
*
buttons
))))
return
0
;
/* Custom buttons */
if
(
taskconfig
->
cButtons
&&
taskconfig
->
pButtons
)
for
(
i
=
0
;
i
<
taskconfig
->
cButtons
;
i
++
)
taskdialog_init_button
(
&
buttons
[
count
++
],
desc
,
taskconfig
->
pButtons
[
i
].
nButtonID
,
taskconfig
->
pButtons
[
i
].
pszButtonText
,
TRUE
);
/* Common buttons */
taskdialog_init_common_buttons
(
desc
,
buttons
,
&
count
);
/* There must be at least one button */
if
(
count
==
0
)
taskdialog_init_button
(
&
buttons
[
count
++
],
desc
,
IDOK
,
MAKEINTRESOURCEW
(
IDS_BUTTON_OK
),
FALSE
);
/* For easy handling just allocate as many lines as buttons, the worst case. */
line_widths
=
Alloc
(
count
*
sizeof
(
*
line_widths
));
/* Separate buttons into lines */
location_x
=
DIALOG_SPACING
;
for
(
i
=
0
,
line_count
=
0
;
i
<
count
;
i
++
)
{
if
(
location_x
+
buttons
[
i
].
width
+
DIALOG_SPACING
>
desc
->
dialog_width
)
{
location_x
=
DIALOG_SPACING
;
line_count
++
;
}
buttons
[
i
].
line
=
line_count
;
location_x
+=
buttons
[
i
].
width
+
DIALOG_SPACING
;
line_widths
[
line_count
]
+=
buttons
[
i
].
width
+
DIALOG_SPACING
;
}
line_count
++
;
/* Try to balance lines so they are about the same size */
for
(
i
=
1
;
i
<
line_count
-
1
;
i
++
)
{
int
diff_now
=
abs
(
line_widths
[
i
]
-
line_widths
[
i
-
1
]);
unsigned
int
j
,
last_button
=
0
;
int
diff_changed
;
for
(
j
=
0
;
j
<
count
;
j
++
)
if
(
buttons
[
j
].
line
==
i
-
1
)
last_button
=
j
;
/* Difference in length of both lines if we wrapped the last button from the last line into this one */
diff_changed
=
abs
(
2
*
buttons
[
last_button
].
width
+
line_widths
[
i
]
-
line_widths
[
i
-
1
]);
if
(
diff_changed
<
diff_now
)
{
buttons
[
last_button
].
line
=
i
;
line_widths
[
i
]
+=
buttons
[
last_button
].
width
;
line_widths
[
i
-
1
]
-=
buttons
[
last_button
].
width
;
}
}
/* Calculate left alignment so all lines are as far right as possible. */
for
(
i
=
0
;
i
<
line_count
;
i
++
)
{
int
new_alignment
=
desc
->
dialog_width
-
line_widths
[
i
];
if
(
new_alignment
<
alignment
)
alignment
=
new_alignment
;
}
/* Now that we got them all positioned, create all buttons */
location_x
=
alignment
;
for
(
i
=
0
;
i
<
count
;
i
++
)
{
if
(
i
>
0
&&
buttons
[
i
].
line
!=
buttons
[
i
-
1
].
line
)
/* New line */
{
location_x
=
alignment
;
desc
->
dialog_height
+=
DIALOG_BUTTON_HEIGHT
+
DIALOG_SPACING
;
}
size
+=
taskdialog_add_control
(
desc
,
buttons
[
i
].
id
,
WC_BUTTONW
,
buttons
[
i
].
hinst
,
buttons
[
i
].
text
,
location_x
,
desc
->
dialog_height
,
buttons
[
i
].
width
,
DIALOG_BUTTON_HEIGHT
);
location_x
+=
buttons
[
i
].
width
+
DIALOG_SPACING
;
}
/* Add height for last row and spacing */
desc
->
dialog_height
+=
DIALOG_BUTTON_HEIGHT
+
DIALOG_SPACING
;
Free
(
line_widths
);
Free
(
buttons
);
return
size
;
}
...
...
@@ -307,7 +442,7 @@ static DLGTEMPLATE *create_taskdialog_template(const TASKDIALOGCONFIG *taskconfi
size
+=
taskdialog_add_main_instruction
(
&
desc
);
size
+=
taskdialog_add_content
(
&
desc
);
size
+=
taskdialog_add_
common_
buttons
(
&
desc
);
size
+=
taskdialog_add_buttons
(
&
desc
);
template
=
Alloc
(
size
);
if
(
!
template
)
...
...
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