patch from Utensil Candel which refactors and documents the AutoCaptureMechanism class
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@58091 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -31,6 +31,9 @@
|
|||||||
// AutoCaptureMechanism
|
// AutoCaptureMechanism
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
wxString AutoCaptureMechanism::default_dir = _T("screenshots");
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
void AutoCaptureMechanism::Delay(int seconds)
|
void AutoCaptureMechanism::Delay(int seconds)
|
||||||
{
|
{
|
||||||
@@ -73,6 +76,8 @@ wxBitmap AutoCaptureMechanism::Capture(int x, int y, int width, int height, int
|
|||||||
|
|
||||||
#else // Under other paltforms, take a real screenshot
|
#else // Under other paltforms, take a real screenshot
|
||||||
|
|
||||||
|
wxUnusedVar(delay);
|
||||||
|
|
||||||
// Create a DC for the whole screen area
|
// Create a DC for the whole screen area
|
||||||
wxScreenDC dcScreen;
|
wxScreenDC dcScreen;
|
||||||
|
|
||||||
@@ -114,6 +119,23 @@ wxBitmap AutoCaptureMechanism::Capture(wxRect rect, int delay)
|
|||||||
return Capture(origin.x, origin.y, rect.GetWidth(), rect.GetHeight(), delay);
|
return Capture(origin.x, origin.y, rect.GetWidth(), rect.GetHeight(), delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
void AutoCaptureMechanism::Save(wxBitmap screenshot, wxString fileName)
|
||||||
|
{
|
||||||
|
// make sure default_dir exists
|
||||||
|
if (!wxDirExists(default_dir))
|
||||||
|
wxMkdir(default_dir);
|
||||||
|
|
||||||
|
wxFileName fullFileName(default_dir, fileName + ".png");
|
||||||
|
|
||||||
|
// do not overwrite already existing files with this name
|
||||||
|
while (fullFileName.FileExists())
|
||||||
|
fullFileName.SetName(fullFileName.GetName() + "_");
|
||||||
|
|
||||||
|
// save the screenshot as a PNG
|
||||||
|
screenshot.SaveFile(fullFileName.GetFullPath(), wxBITMAP_TYPE_PNG);
|
||||||
|
}
|
||||||
|
|
||||||
void AutoCaptureMechanism::CaptureAll()
|
void AutoCaptureMechanism::CaptureAll()
|
||||||
{
|
{
|
||||||
// start from the first page
|
// start from the first page
|
||||||
@@ -133,10 +155,25 @@ void AutoCaptureMechanism::CaptureAll()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// // create the screenshot
|
||||||
|
// wxBitmap screenshot = Capture(ctrl);
|
||||||
|
// if (ctrl.flag & AJ_Union)
|
||||||
|
// screenshot = Union(screenshot, Capture(*(++it)));
|
||||||
|
//
|
||||||
|
// // and save it
|
||||||
|
// Save(screenshot, ctrl.name);
|
||||||
// create the screenshot
|
// create the screenshot
|
||||||
wxBitmap screenshot = Capture(ctrl);
|
wxBitmap screenshot = Capture(ctrl);
|
||||||
|
|
||||||
if(ctrl.flag & AJ_Union)
|
if(ctrl.flag & AJ_Union)
|
||||||
screenshot = Union(screenshot, Capture(*(++it)));
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
ctrl = *(++it);
|
||||||
|
screenshot = Union(screenshot, Capture(ctrl));
|
||||||
|
}
|
||||||
|
while(!(ctrl.flag & AJ_UnionEnd));
|
||||||
|
}
|
||||||
|
|
||||||
// and save it
|
// and save it
|
||||||
Save(screenshot, ctrl.name);
|
Save(screenshot, ctrl.name);
|
||||||
@@ -209,14 +246,8 @@ wxBitmap AutoCaptureMechanism::Union(wxBitmap pic1, wxBitmap pic2)
|
|||||||
|
|
||||||
wxBitmap result(w, h, -1);
|
wxBitmap result(w, h, -1);
|
||||||
|
|
||||||
wxMemoryDC dstDC;
|
#if 0
|
||||||
dstDC.SelectObject(result);
|
//Mask the bitmap "result"
|
||||||
|
|
||||||
dstDC.DrawBitmap(pic1, 0, 0, false);
|
|
||||||
dstDC.DrawBitmap(pic2, 0, h1 + gap_between, false);
|
|
||||||
|
|
||||||
dstDC.SelectObject(wxNullBitmap);
|
|
||||||
|
|
||||||
wxMemoryDC maskDC;
|
wxMemoryDC maskDC;
|
||||||
wxBitmap mask(w, h, 1);
|
wxBitmap mask(w, h, 1);
|
||||||
maskDC.SelectObject(mask);
|
maskDC.SelectObject(mask);
|
||||||
@@ -231,26 +262,22 @@ wxBitmap AutoCaptureMechanism::Union(wxBitmap pic1, wxBitmap pic2)
|
|||||||
maskDC.SelectObject(wxNullBitmap);
|
maskDC.SelectObject(wxNullBitmap);
|
||||||
|
|
||||||
result.SetMask(new wxMask(mask));
|
result.SetMask(new wxMask(mask));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
wxMemoryDC dstDC;
|
||||||
|
dstDC.SelectObject(result);
|
||||||
|
|
||||||
|
dstDC.SetPen(*wxTRANSPARENT_PEN);
|
||||||
|
dstDC.SetBrush(*wxWHITE_BRUSH);
|
||||||
|
dstDC.DrawRectangle(-1, -1, w + 1, h + 1);
|
||||||
|
dstDC.DrawBitmap(pic1, 0, 0, false);
|
||||||
|
dstDC.DrawBitmap(pic2, 0, h1 + gap_between, false);
|
||||||
|
|
||||||
|
dstDC.SelectObject(wxNullBitmap);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoCaptureMechanism::Save(wxBitmap screenshot, wxString fileName)
|
|
||||||
{
|
|
||||||
// make sure m_dir exists
|
|
||||||
if (!wxDirExists(m_dir))
|
|
||||||
wxMkdir(m_dir);
|
|
||||||
|
|
||||||
wxFileName fullFileName(m_dir, fileName + ".png");
|
|
||||||
|
|
||||||
// do not overwrite already existing files with this name
|
|
||||||
while (fullFileName.FileExists())
|
|
||||||
fullFileName.SetName(fullFileName.GetName() + "_");
|
|
||||||
|
|
||||||
// save the screenshot as a PNG
|
|
||||||
screenshot.SaveFile(fullFileName.GetFullPath(), wxBITMAP_TYPE_PNG);
|
|
||||||
}
|
|
||||||
|
|
||||||
wxRect AutoCaptureMechanism::GetRect(wxWindow* ctrl, int flag)
|
wxRect AutoCaptureMechanism::GetRect(wxWindow* ctrl, int flag)
|
||||||
{
|
{
|
||||||
if (flag & AJ_RegionAdjust)
|
if (flag & AJ_RegionAdjust)
|
||||||
@@ -272,7 +299,7 @@ wxRect AutoCaptureMechanism::GetRect(wxWindow* ctrl, int flag)
|
|||||||
+---------+-----------+---------+
|
+---------+-----------+---------+
|
||||||
*/
|
*/
|
||||||
|
|
||||||
m_grid = new wxFlexGridSizer(3, 3, m_border, m_border);
|
m_grid = new wxFlexGridSizer(3, 3, m_margin, m_margin);
|
||||||
|
|
||||||
wxStaticText* l[4];
|
wxStaticText* l[4];
|
||||||
|
|
||||||
@@ -302,12 +329,12 @@ wxRect AutoCaptureMechanism::GetRect(wxWindow* ctrl, int flag)
|
|||||||
}
|
}
|
||||||
else // Actually it won't get here working with the current guiframe.h/guiframe.cpp
|
else // Actually it won't get here working with the current guiframe.h/guiframe.cpp
|
||||||
{
|
{
|
||||||
return ctrl->GetScreenRect().Inflate(m_border);
|
return ctrl->GetScreenRect().Inflate(m_margin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return ctrl->GetScreenRect().Inflate(m_border);
|
return ctrl->GetScreenRect().Inflate(m_margin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -14,65 +14,315 @@
|
|||||||
|
|
||||||
#include <wx/notebook.h>
|
#include <wx/notebook.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
GlobalAdjustFlags works with AutoCaptureMechanism's constructor, to disbale/enable
|
||||||
|
some auto-adjustment for all controls.
|
||||||
|
|
||||||
// TODO: document what these flags mean
|
They are used to make AutoCaptureMechanism more configurable and provide a fallback
|
||||||
|
to detect the bugs that the adjustments intended to avoid.
|
||||||
|
|
||||||
|
@see AdjustFlags
|
||||||
|
*/
|
||||||
|
enum GlobalAdjustFlags
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
This is the default. All adjustments instructed in
|
||||||
|
AutoCaptureMechanism::RegisterControl() will be performed.
|
||||||
|
*/
|
||||||
|
AJ_NormalAll = 0,
|
||||||
|
|
||||||
|
/**
|
||||||
|
Disable region adjustment for all controls.
|
||||||
|
*/
|
||||||
|
AJ_DisableRegionAdjust = 1 << 0,
|
||||||
|
|
||||||
|
/**
|
||||||
|
Enable region adjustment for all controls.
|
||||||
|
*/
|
||||||
|
AJ_AlwaysRegionAdjust = 1 << 1,
|
||||||
|
|
||||||
|
/**
|
||||||
|
Disable name adjustment for all controls.
|
||||||
|
*/
|
||||||
|
AJ_DisableNameAdjust = 1 << 2,
|
||||||
|
|
||||||
|
/**
|
||||||
|
For all the "Drop-down Controls", e.g. wxChoice, do not prompt the user about whether
|
||||||
|
to capture their drop-down state, and always capture only its non-drop-down state.
|
||||||
|
*/
|
||||||
|
AJ_DisableDropdown = 1 << 3
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
AdjustFlags works with AutoCaptureMechanism::RegisterControl() to specify how to
|
||||||
|
adjust the screenshot of the current control.
|
||||||
|
|
||||||
|
They are used to avoid bugs, look better or interact with user etc.
|
||||||
|
|
||||||
|
@see GlobalAdjustFlags
|
||||||
|
*/
|
||||||
enum AdjustFlags
|
enum AdjustFlags
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
This is the default. Perform no adjustment for this control.
|
||||||
|
*/
|
||||||
AJ_Normal = 0,
|
AJ_Normal = 0,
|
||||||
|
|
||||||
|
/**
|
||||||
|
Perform region adjustment for this control.
|
||||||
|
|
||||||
|
On some platforms and for some controls, wxWindow::GetScreenRect() will return
|
||||||
|
a smaller or deflected region. In these cases, the screenshots we get are incomplete.
|
||||||
|
It's recommended for everyone to fix the controls' code, yet this flag provides a
|
||||||
|
workaround to get a guaranteed correct region without using wxWindow::GetScreenRect().
|
||||||
|
|
||||||
|
This workaround("label trick") is inspired by (or say stolen from) Auria's work.
|
||||||
|
*/
|
||||||
AJ_RegionAdjust = 1 << 0,
|
AJ_RegionAdjust = 1 << 0,
|
||||||
|
|
||||||
|
/**
|
||||||
|
This flag provides a way to capture the drop-down state of "Drop-down Controls",
|
||||||
|
e.g. wxChoice.
|
||||||
|
|
||||||
|
For all the "Drop-down Controls", prompt the user about whether to capture their
|
||||||
|
drop-down state, if the user chooses YES, he should drop down the control in about
|
||||||
|
3 seconds and wait util it's captured in that state.
|
||||||
|
*/
|
||||||
AJ_Dropdown = 1 << 1,
|
AJ_Dropdown = 1 << 1,
|
||||||
|
|
||||||
|
/**
|
||||||
|
This flag is used internally by RegisterPageTurn(). Don't use it directly unless you
|
||||||
|
know what you are doing.
|
||||||
|
*/
|
||||||
AJ_TurnPage = 1 << 2,
|
AJ_TurnPage = 1 << 2,
|
||||||
|
|
||||||
|
/**
|
||||||
|
This flag provides a functionality to union screenshots of different controls into
|
||||||
|
one image.
|
||||||
|
|
||||||
|
It's especially useful to demonstrate different modes/states of a control,
|
||||||
|
e.g. the single-line/multi-line modes of a wxTextCtrl.
|
||||||
|
|
||||||
|
For a series of controls to be unioned, you should specify AJ_Union for the first,
|
||||||
|
and AJ_UnionEnd for the last. For the controls between them, you can either specify
|
||||||
|
AJ_Union or not.
|
||||||
|
*/
|
||||||
AJ_Union = 1 << 3,
|
AJ_Union = 1 << 3,
|
||||||
|
|
||||||
|
/**
|
||||||
|
@see AJ_Union.
|
||||||
|
*/
|
||||||
AJ_UnionEnd = 1 << 4
|
AJ_UnionEnd = 1 << 4
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
@class AutoCaptureMechanism
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
AutoCaptureMechanism provides an easy-to-use and adjustable facility to take the screenshots
|
||||||
// class AutoCaptureMechanism
|
for all controls fully automaticly and correctly. It also provides an advanced feature to
|
||||||
// ----------------------------------------------------------------------------
|
union screenshots of different states/modes of a control.
|
||||||
|
|
||||||
|
@section tag_filename_convention Screenshot File Name Convention
|
||||||
|
|
||||||
|
All screenshots are generated as PNG files. For a control named wxName, its screenshot file
|
||||||
|
name would be "name.png", e.g. "button.png" for wxButton. This is the protocol with the
|
||||||
|
doxygen document of wxWidgets.
|
||||||
|
|
||||||
|
By default, screenshots are generated under the subdirectory "screenshots" of current working
|
||||||
|
directory. During updating or adding new screenshots, first make sure screenshots are generated
|
||||||
|
correctly, and then copy them to the following subdirectory of docs/doxygen/images:
|
||||||
|
|
||||||
|
"wxmsw" for MS Windows, "wxgtk" for Linux and "wxmac" for Mac OS.
|
||||||
|
|
||||||
|
@section tag_gui_assumption The Assumption of GUI
|
||||||
|
|
||||||
|
Unfortunately, this class have an assumption about the structure of GUI:
|
||||||
|
It must have the follwoing top-down structure:
|
||||||
|
|
||||||
|
wxNotebook->wxPanel->wxSizer->wxControl
|
||||||
|
|
||||||
|
That means, in the wxNotebook associated with this class, controls that needs to be
|
||||||
|
taken screenshots are placed on different panels(for grouping) and layed out by wxSizers.
|
||||||
|
|
||||||
|
@section tag_tutorial Tutorial
|
||||||
|
|
||||||
|
In the contruction, you should associate a wxNotebook with this class, in that wxNotebook,
|
||||||
|
controls that needs to be captured are placed on different panels(for grouping).
|
||||||
|
|
||||||
|
When you register controls, you should do it in order: Register the controls on the first
|
||||||
|
panel(using RegisterControl()), and then register a page turn(using RegisterPageTurn()),
|
||||||
|
so this class can turn a page of the wxNotebook to present the second page. And then
|
||||||
|
you register the controls on the second panel, then a page turn, and so on.
|
||||||
|
|
||||||
|
When you are done, simply call CaptureAll(), then screenshots of all controls will be
|
||||||
|
automaticly generated.
|
||||||
|
|
||||||
|
@section tag_autoadjust Make Use of Auto Adjustments
|
||||||
|
|
||||||
|
First take a look at the document of RegisterControl(), enum AdjustFlags and
|
||||||
|
GlobalAdjustFlags.
|
||||||
|
|
||||||
|
And then, ScreenshotFrame::OnCaptureAllControls() is a good example of making use of
|
||||||
|
auto adjustment. Taking a look at it will get you started.
|
||||||
|
|
||||||
|
@section tag_developer_note Notes for Developers
|
||||||
|
|
||||||
|
@subsection tag_cnc CaptureAll() and Capture()
|
||||||
|
|
||||||
|
The implementation of Auto Adjustments is in CaptureAll() and Capture(), the code is
|
||||||
|
short, quite readable and well commented, please read the codes before any modification.
|
||||||
|
|
||||||
|
If you need the class to do something sepcial for you, consider introducing a new flag
|
||||||
|
and implement it in them. For an operation performed on multiple controls, implemente
|
||||||
|
its logic in CaptureAll(), otherwise in the private member Capture().
|
||||||
|
|
||||||
|
@subsection tag_yield_issue wxYield Issues
|
||||||
|
|
||||||
|
Not quite a good habit, but this class made a lot of use of wxYield()/wxYieldIfNeeded().
|
||||||
|
They are used to ensure the update of GUI(e.g. the page turn of wxNotebook) is done
|
||||||
|
before any further screenshot-taking, or to do the timing(in Delay()). Without their use,
|
||||||
|
there would be subtle bugs.
|
||||||
|
|
||||||
|
I've read documents about wxYield() and understand the down side of it before using it.
|
||||||
|
But I didn't find a better approach to do those things, and I used them carefully. So
|
||||||
|
please DO NOT remove any of these wxYield()s unless you're sure that it won't cause problems
|
||||||
|
on all of MS Windows XP/Vista, Linux(Ubuntu/Fedora), Mac OS Tiger/Leopard. And please
|
||||||
|
help me to find a better approach, thank you :)
|
||||||
|
*/
|
||||||
class AutoCaptureMechanism
|
class AutoCaptureMechanism
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
Constructor.
|
||||||
|
|
||||||
|
@param notebook
|
||||||
|
The wxNotebook associated with this class.Please see @ref tag_gui_assumption
|
||||||
|
and @ref tag_tutorial.
|
||||||
|
|
||||||
|
@param flag
|
||||||
|
It's one of or a combination of GlobalAdjustFlags, to disbale/enable some auto-adjustment
|
||||||
|
for all controls.
|
||||||
|
|
||||||
|
@param margin
|
||||||
|
It's the margin around every control in the sreenshots.
|
||||||
|
*/
|
||||||
AutoCaptureMechanism(wxNotebook *notebook,
|
AutoCaptureMechanism(wxNotebook *notebook,
|
||||||
wxString directory = wxT("screenshots"),
|
int flag = AJ_NormalAll,
|
||||||
int border = 5)
|
int margin = 5)
|
||||||
: m_notebook(notebook), m_dir(directory), m_border(border) {}
|
: m_notebook(notebook), m_flag(flag),
|
||||||
|
m_margin(margin), m_grid(NULL) {}
|
||||||
|
|
||||||
~AutoCaptureMechanism(){}
|
~AutoCaptureMechanism(){}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
If wxRTTI can't get the name correctly, specify name;
|
Register a control and perform specifid auto adjustments.
|
||||||
If wxWindow::GetScreenRect doesn't get the rect correctly, set flag to AJ_RegionAdjust
|
|
||||||
|
@param ctrl
|
||||||
|
The pointer to the control to be taken a screenshot.
|
||||||
|
|
||||||
|
@param name
|
||||||
|
If you find out that the screenshot for this control was generated under an incorrect
|
||||||
|
file name, specify @a name. e.g. for wxButton, "wxButton" or "button" are both OK.
|
||||||
|
|
||||||
|
@param flag
|
||||||
|
|
||||||
|
If you end up with an a smaller or deflected screenshot, use AJ_RegionAdjust.
|
||||||
|
|
||||||
|
If you want to caputure the "drop-down" state of a "drop-down" control, use AJ_Dropdown.
|
||||||
|
|
||||||
|
If you want to present different states of a control in one screenshot, use AJ_Union
|
||||||
|
and AJ_UnionEnd.
|
||||||
|
|
||||||
|
Please read the document of enum AdjustFlags, and notice that this flag could be enabled/
|
||||||
|
disabled by global flag GlobalAdjustFlags.
|
||||||
*/
|
*/
|
||||||
void RegisterControl(wxWindow * ctrl, wxString name = wxT(""),
|
void RegisterControl(wxWindow * ctrl, wxString name = _T(""), int flag = AJ_Normal)
|
||||||
int flag = AJ_Normal)
|
|
||||||
{
|
{
|
||||||
m_controlList.push_back(Control(ctrl, name, flag));
|
m_controlList.push_back(Control(ctrl, name, flag));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Register a control and perform specifid auto adjustments.
|
||||||
|
|
||||||
|
This is the same as RegisterControl(wxWindow * ctrl, wxString name, int flag),
|
||||||
|
But with it, you won't have to specify the name if you only want to auto-adjust something
|
||||||
|
other than name adjustment.
|
||||||
|
*/
|
||||||
void RegisterControl(wxWindow * ctrl, int flag)
|
void RegisterControl(wxWindow * ctrl, int flag)
|
||||||
{
|
{
|
||||||
RegisterControl(ctrl, wxT(""), flag);
|
RegisterControl(ctrl, _T(""), flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Register a page turn.
|
||||||
|
|
||||||
|
When you finished registering the controls on a panel, remember to call it to turn the
|
||||||
|
wxNotebook to the next panel.
|
||||||
|
*/
|
||||||
void RegisterPageTurn()
|
void RegisterPageTurn()
|
||||||
{
|
{
|
||||||
m_controlList.push_back(Control(0, wxT(""), AJ_TurnPage));
|
m_controlList.push_back(Control(0, _T(""), AJ_TurnPage));
|
||||||
}
|
}
|
||||||
|
|
||||||
// capture all controls of the associated notebook
|
/**
|
||||||
|
Capture all registered controls of the associated wxNotebook.
|
||||||
|
*/
|
||||||
void CaptureAll();
|
void CaptureAll();
|
||||||
|
|
||||||
// take a screenshot only of the given rect
|
/*
|
||||||
// delay is only useful for Mac, for fixing a delay bug
|
Static Members
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
Take a screenshot for the given region.
|
||||||
|
|
||||||
|
@param rect is the given rectangular region.
|
||||||
|
|
||||||
|
@param delay is only useful for Mac, for fixing a delay bug. It seems that it didn't
|
||||||
|
fix the bug, so it might be removed soon.
|
||||||
|
*/
|
||||||
static wxBitmap Capture(wxRect rect, int delay = 0);
|
static wxBitmap Capture(wxRect rect, int delay = 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Take a screenshot for the given region.
|
||||||
|
|
||||||
|
@see Capture(wxRect rect, int delay)
|
||||||
|
*/
|
||||||
static wxBitmap Capture(int x, int y, int width, int height, int delay = 0);
|
static wxBitmap Capture(int x, int y, int width, int height, int delay = 0);
|
||||||
|
|
||||||
static void Delay(int seconds);
|
/**
|
||||||
|
Save the screenshot as the name of @a fileName in the default directory.
|
||||||
|
|
||||||
|
@a fileName should be without ".png".
|
||||||
|
*/
|
||||||
|
static void Save(wxBitmap screenshot, wxString fileName);
|
||||||
|
|
||||||
private: // internal utils
|
/**
|
||||||
|
Set the default directory where the screenshots will be generated.
|
||||||
|
*/
|
||||||
|
static void SetDefaultDirectory(wxString dir) { default_dir = dir; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the default directory where the screenshots will be generated.
|
||||||
|
*/
|
||||||
|
static wxString GetDefaultDirectory() { return default_dir; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the absolute path of the default directory where the screenshots will be generated.
|
||||||
|
*/
|
||||||
|
static wxString GetDefaultDirectoryAbsPath()
|
||||||
|
{
|
||||||
|
wxFileName output = wxFileName::DirName(GetDefaultDirectory());
|
||||||
|
output.MakeAbsolute();
|
||||||
|
return output.GetFullPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/*
|
||||||
|
Internal Data Structures
|
||||||
|
|
||||||
|
They might go public in future to provide reuse of ControlList.
|
||||||
|
*/
|
||||||
struct Control
|
struct Control
|
||||||
{
|
{
|
||||||
Control() {}
|
Control() {}
|
||||||
@@ -85,31 +335,76 @@ private: // internal utils
|
|||||||
int flag;
|
int flag;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef std::vector<Control> ControlList;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Internal Functions
|
||||||
|
|
||||||
|
They are only used to clearify the logic of some public functions and it's nonsense
|
||||||
|
to call them elsewhere.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Capture and auto adjust the control. Used by CaptureAll().
|
||||||
|
*/
|
||||||
wxBitmap Capture(Control & ctrl);
|
wxBitmap Capture(Control & ctrl);
|
||||||
|
|
||||||
// if AJ_RegionAdjust is specified, the following line will use the label
|
/*
|
||||||
// trick to adjust the region position and size
|
Get the correct rectangular region that the control occupies. Used by
|
||||||
|
Capture(Control & ctrl).
|
||||||
|
|
||||||
|
If AJ_RegionAdjust is specified, it will use the "label trick" to perform
|
||||||
|
region auto adjustment.
|
||||||
|
|
||||||
|
The "label trick" is to reattach the control to a wxFlexGridSizer m_grid,
|
||||||
|
surround the control with labels and get the control's region by label's positions.
|
||||||
|
Just like this:
|
||||||
|
|
||||||
|
+---------+-----------+---------+
|
||||||
|
| 0 | label | 1 |
|
||||||
|
+---------+-----------+---------+
|
||||||
|
| label | ctrl | label |
|
||||||
|
+---------+-----------+---------+
|
||||||
|
| 2 | label | 3 |
|
||||||
|
+---------+-----------+---------+
|
||||||
|
|
||||||
|
So, there will be a side effect: the control is moved to a new position. So after taking the
|
||||||
|
screenshot, Capture(Control & ctrl) should call PutBack(wxWindow * ctrl) to put it back.
|
||||||
|
|
||||||
|
If AJ_RegionAdjust isn't specified, it will simply call wxWindow::GetScreenRect().
|
||||||
|
*/
|
||||||
wxRect GetRect(wxWindow* ctrl, int flag);
|
wxRect GetRect(wxWindow* ctrl, int flag);
|
||||||
|
|
||||||
// put the control back after the label trick(Using reparent/resizer approach)
|
/*
|
||||||
|
Put the control back after the label trick used in GetRect(). Used by
|
||||||
|
Capture(Control & ctrl).
|
||||||
|
*/
|
||||||
void PutBack(wxWindow * ctrl);
|
void PutBack(wxWindow * ctrl);
|
||||||
|
|
||||||
wxBitmap Union(wxBitmap pic1, wxBitmap pic2);
|
/*
|
||||||
|
Union two screenshots in the vertical direction, and leave a gap between the
|
||||||
|
screenshots. Used by CaptureAll().
|
||||||
|
|
||||||
void Save(wxBitmap screenshot, wxString fileName);
|
The gap is 20 pixels by default. Currently it isn't configurable.
|
||||||
|
*/
|
||||||
|
static wxBitmap Union(wxBitmap pic1, wxBitmap pic2);
|
||||||
|
|
||||||
typedef std::vector<Control> ControlList;
|
static void Delay(int seconds);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Data Members
|
||||||
|
*/
|
||||||
ControlList m_controlList;
|
ControlList m_controlList;
|
||||||
|
|
||||||
// here we introduce the dependency on wxNotebook.
|
|
||||||
// The assumption of this whole class is that the gui has the following top-down structure
|
|
||||||
// wxNotebook wxPanel wxSizer wxControls
|
|
||||||
wxNotebook* m_notebook;
|
wxNotebook* m_notebook;
|
||||||
|
|
||||||
|
int m_flag;
|
||||||
|
|
||||||
|
int m_margin;
|
||||||
|
|
||||||
wxFlexGridSizer* m_grid;
|
wxFlexGridSizer* m_grid;
|
||||||
|
|
||||||
wxString m_dir;
|
static wxString default_dir;
|
||||||
int m_border;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _AUTOCAPTURE_H_
|
#endif // _AUTOCAPTURE_H_
|
||||||
|
@@ -54,15 +54,12 @@ void ScreenshotFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
|
|||||||
|
|
||||||
void ScreenshotFrame::OnSeeScreenshots(wxCommandEvent& WXUNUSED(event))
|
void ScreenshotFrame::OnSeeScreenshots(wxCommandEvent& WXUNUSED(event))
|
||||||
{
|
{
|
||||||
wxFileName defaultDir = wxFileName::DirName(GetDefaultDirectory());
|
wxString defaultDir = AutoCaptureMechanism::GetDefaultDirectoryAbsPath();
|
||||||
defaultDir.MakeAbsolute();
|
|
||||||
|
|
||||||
// Check if defaultDir already existed
|
if (wxFileName::DirExists(defaultDir))
|
||||||
if (!defaultDir.DirExists())
|
wxLaunchDefaultBrowser(defaultDir);
|
||||||
defaultDir.Mkdir();
|
else
|
||||||
|
wxMessageBox(_("There isn't any screenshots yet."));
|
||||||
// Use the native file browser to open defaultDir
|
|
||||||
wxLaunchDefaultBrowser(defaultDir.GetFullPath());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScreenshotFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
|
void ScreenshotFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
|
||||||
@@ -85,20 +82,18 @@ void ScreenshotFrame::OnCaptureFullScreen(wxCommandEvent& WXUNUSED(event))
|
|||||||
wxCoord screenWidth, screenHeight;
|
wxCoord screenWidth, screenHeight;
|
||||||
dcScreen.GetSize(&screenWidth, &screenHeight);
|
dcScreen.GetSize(&screenWidth, &screenHeight);
|
||||||
|
|
||||||
const wxString fullscreen_filename = GetDefaultDirectoryAbsPath() + _T("fullscreen.png");
|
|
||||||
|
|
||||||
wxBitmap fullscreen = AutoCaptureMechanism::Capture(0, 0, screenWidth, screenHeight);
|
wxBitmap fullscreen = AutoCaptureMechanism::Capture(0, 0, screenWidth, screenHeight);
|
||||||
|
|
||||||
fullscreen.SaveFile(fullscreen_filename, wxBITMAP_TYPE_PNG);
|
AutoCaptureMechanism::Save(fullscreen, _T("fullscreen"));
|
||||||
|
|
||||||
wxMessageBox(_("A screenshot of the entire screen was saved as:\n\n ")
|
wxMessageBox(_("A screenshot of the entire screen was saved as:\n\n ")
|
||||||
+ fullscreen_filename,
|
+ AutoCaptureMechanism::GetDefaultDirectoryAbsPath() + _T("fullscreen.png"),
|
||||||
_("Full screen capture"), wxICON_INFORMATION|wxOK, this);
|
_("Full screen capture"), wxICON_INFORMATION|wxOK, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScreenshotFrame::OnCaptureAllControls(wxCommandEvent& WXUNUSED(event))
|
void ScreenshotFrame::OnCaptureAllControls(wxCommandEvent& WXUNUSED(event))
|
||||||
{
|
{
|
||||||
wxString dir = GetDefaultDirectoryAbsPath();
|
wxString dir = AutoCaptureMechanism::GetDefaultDirectoryAbsPath();
|
||||||
|
|
||||||
// check if there are other screenshots taken before
|
// check if there are other screenshots taken before
|
||||||
if (wxFileName::DirExists(dir))
|
if (wxFileName::DirExists(dir))
|
||||||
|
@@ -26,20 +26,6 @@ protected: // event handlers
|
|||||||
|
|
||||||
virtual void OnCaptureFullScreen( wxCommandEvent& event );
|
virtual void OnCaptureFullScreen( wxCommandEvent& event );
|
||||||
virtual void OnCaptureAllControls( wxCommandEvent& event );
|
virtual void OnCaptureAllControls( wxCommandEvent& event );
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
// Before a config class is written, these two functions are placed here.
|
|
||||||
// It's only a transition and they wil be removed soon
|
|
||||||
wxString GetDefaultDirectory() const { return _T("screenshots"); }
|
|
||||||
|
|
||||||
wxString GetDefaultDirectoryAbsPath() const
|
|
||||||
{
|
|
||||||
wxFileName output = wxFileName::DirName(GetDefaultDirectory());
|
|
||||||
output.MakeAbsolute();
|
|
||||||
return output.GetFullPath();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _SCREENSHOT_MAIN_H_
|
#endif // _SCREENSHOT_MAIN_H_
|
||||||
|
Reference in New Issue
Block a user