For almost 20 year I've been developing an MFC MDI application. It has worked on Windows 98, Windows XP and Windows 7. But it fails on Windows 10... Any ideas, why? Here is the code:
class CEdytorDocFrame : public CMDIChildWnd
{
DECLARE_DYNCREATE(CEdytorDocFrame)
public:
CSplitterWnd m_wndSplitter;
CSplitterWnd m_wndSplitter2;
CStatusBar m_wndStatusBar;
}
IMPLEMENT_DYNCREATE(CEdytorDocFrame, CMDIChildWnd)
CEdytorDocFrame::CEdytorDocFrame() :
m_nOldCY(0),
m_nOldEditH(1),
m_nOldViewH(1),
m_nOldEditMinH(0),
m_nOldViewMinH(0)
{
} // CEdytorDocFrame::CEdytorDocFrame()
BOOL CEdytorDocFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
CDebug::WriteLog("CEdytorDocFrame::OnCreateClient(), enter");
/*
** Create status bar
*/
if(!m_wndStatusBar.CreateEx(this, SBT_TOOLTIPS | SBARS_SIZEGRIP) ||
!m_wndStatusBar.SetIndicators(indicators, countof(indicators)))
{
TRACE0("Failed to create status bar\n");
return FALSE;
}
CDebug::WriteLog("CEdytorDocFrame::OnCreateClient(), status bar created");
/*
** Calculate heights and widths
*/
int wndW, wndH, treeW, treeH, viewW, editW;
wndW = lpcs->cx;
m_nOldCY = wndH = lpcs->cy;
// Set tree pane to be 1/4 of total width and maximum height
treeW = wndW/4;
treeH = 0;
// Set edit pane to be 4/7 height of edit window and maximum width
m_nOldEditH = MulDiv(wndH, 4, 7);
editW = 0;
// Set preview pane to be 3/7 height of edit window and maximum width
m_nOldViewH = wndH-m_nOldEditH;
viewW = 0;
CDebug::WriteLog("CEdytorDocFrame::OnCreateClient() wndW=%d, wndH=%d, treeW=%d, treeH=%d, viewW=%d, editW=%d",
wndW, wndH, treeW, treeH, viewW, editW);
// Create panels
if(!m_wndSplitter.CreateStatic(this, 1, 2))
{
TRACE0("Failed to create static splitter\n");
return FALSE;
}
CDebug::WriteLog("CEdytorDocFrame::OnCreateClient(), 1st splitter created");
Last WriteLog() does not get executed, so I suspect some problem with CreateStatic()... But why on Windows 10 only?
Related
I'm writing an integration test using QTest in which as soon as I click into the viewport of the widget, a multiline popup QInputDialog appears which blocks the further execution of code and requires manually canceling the dialog. Here is the code:
void PartTest::testTypewriterAnnotTool()
{
Okular::Part part(nullptr, nullptr, QVariantList()); // It is the main widget of PDF reader comprising of viewport where PDF page is shown
part.openUrl(QUrl::fromLocalFile(QStringLiteral(KDESRCDIR "data/file1.pdf"))); // open file1.pdf
part.widget()->show();
QVERIFY(QTest::qWaitForWindowExposed(part.widget()));
// Width and height of pageView widget, the child of Part widget which shows the PDF page
const int width = part.m_pageView->horizontalScrollBar()->maximum() +
part.m_pageView->viewport()->width();
const int height = part.m_pageView->verticalScrollBar()->maximum() +
part.m_pageView->viewport()->height();
part.m_document->setViewportPage(0); // sets viewport page 0, i.e. page number 1
QMetaObject::invokeMethod(part.m_pageView, "slotToggleAnnotator", Q_ARG( bool, true )); // toggles and shows the annotation toolbar with all tools avaialable
QList<QToolButton *> toolbuttonList = part.m_pageView->findChildren<QToolButton *>(); // find a list of annotation toolbutton
// Check if the tooltip of 10th button is "Typewriter"
QToolButton* typewriterButton = toolbuttonList.at(9);
QCOMPARE( typewriterButton->toolTip(), QStringLiteral("Typewriter") );
typewriterButton->click(); // clicking and selecting typewriter annotation tool
QTest::mouseMove(part.m_pageView->viewport(), QPoint(width * 0.5, height * 0.2)); // leading mouse pointer to a specific point in the viewport
QTest::mouseClick(part.m_pageView->viewport(), Qt::LeftButton, Qt::NoModifier, QPoint(width * 0.5, height * 0.2)); // mouse left button click on the viewport and a popup dialog with 'add a new note' appears
}
I have to write a test case where I have to grab that popup dialog and programmatically close it. I'm trying to achieve so by using the QTimer where I will execute a function to grab the dialog after 1 second of clicking in the viewport and then trying to close it like this:
class PartTest
{
...
private:
Okular::part *m_part;
}
void PartTest::testTypewriterAnnotTool()
{
...
m_part = ∂
QTimer* mTimer = new QTimer(this);
mTimer->setSingleShot(true);
connect(mTimer, SIGNAL(timeout()), SLOT(testDialogClosed()));
mTimer->start(1000);
QTest::mouseClick(part.m_pageView->viewport(), Qt::LeftButton, Qt::NoModifier, QPoint(width * 0.5, height * 0.2));
}
void PartTest::testDialogClosed()
{
bool m_clicked = false;
QDialog *dialog = m_part->widget()->findChild<QDialog*>();
if (dialog)
{
QDialogButtonBox *buttonBox = dialog->findChild<QDialogButtonBox*>();
buttonBox->button(QDialogButtonBox::Cancel)->click();
m_clicked = true;
}
QVERIFY(m_clicked);
}
Here, QVERIFY(m_clicked) test case always "fail" that means the popup QInputDialog is not the child of Okular::Part and I'm not getting a way to grab the pointer to this dialog window and close it. Any help?
You can enumerate the top-level widgets and find the dialog that way:
template <class P> QList<P> topLevelWidgets() {
QList<P> widgets
for (auto *w : QApplication::topLevelWidgets())
if (auto *t = qobject_cast<P>(w))
widgets << t;
return widgets;
}
template <class P> P topLevelWidget() {
auto w = topLevelWidgets<P>();
return (w.size() == 1) ? w.first() : nullptr;
}
void PartTest::testDialogClosed()
{
bool m_clicked = false;
if (auto *dialog = topLevelWidget<QDialog*>())
if (auto *buttonBox = dialog->findChild<QDialogButtonBox*>()) {
buttonBox->button(QDialogButtonBox::Cancel)->click();
m_clicked = true;
}
QVERIFY(m_clicked);
}
I am trying to display a GIF picture as splash as starting of my small program in visual studio. I am really getting crazy. I looked it is possible in Qt IDE but I really need it in visual studio because my other code works only with visual studio. And yes I tried to convert my code for Qt giving me too many errors.
I have seen this post.
I am using GDI+ but still dunno how to simply display it instead of play and stop. It's okay even instead of splash to display a small form that plays the GIF file, can you guys give me a small code snippet in how to do it in c++?
Thanks.
Here is an MFC window class that implements a splash screen using GDI Plus for displaying an (animated) GIF.
I've encapsulated everything inside a header file to simplify using it with your project. Save it as an .h file (maybe "SplashWnd.h"), then include it wherever you want to set up the splash. You app's InitInstance might be a good place to add it - something like this line (before any DoModal calls):
SplashWnd splash(_T("Filname.gif"));
The constructor can also take parameters for controlling the delay before auto-closing, and also specifying a function to call when the splash is closed.
The splash window has no border or caption - it appears only as the loaded image, floating on top of any other windows. Its icon doesn't appear in the taskbar, and will close when its timeout expires, or the user clicks the window or presses a key.
#pragma once
#include <functional>
#include <afxwin.h>
#include <gdiplus.h>
#pragma comment(lib,"gdiplus.lib")
inline void ManageGdiPlusInit(bool release=false) {
static int refcount = 0;
static ULONG_PTR token;
if(release) {
if(--refcount == 0) {
Gdiplus::GdiplusShutdown(token);
}
} else if(++refcount == 1) {
Gdiplus::GdiplusStartupInput startup_input;
Gdiplus::GdiplusStartup(&token, &startup_input, 0);
} }
inline void GdiPlusInit() { ManageGdiPlusInit(false); }
inline void GdiPlusRelease() { ManageGdiPlusInit(true); }
namespace {
class SplashWnd : public CWnd {
protected:
static CString WindowClass() {
static CString name;
if(name.IsEmpty()) {
name = AfxRegisterWndClass(CS_DROPSHADOW, 0, (HBRUSH)GetStockObject(GRAY_BRUSH), 0);
}
return name;
}
Gdiplus::Image *m_pImage;
UINT m_FrameCount;
unsigned char *m_FrameDelayData;
const UINT *m_FrameDelays;
UINT m_CurFrameIndex;
UINT m_AnimationTimerId;
UINT m_ExpireTimerId;
CRect m_WindowRect;
std::function<void()> m_DismissCallback;
DECLARE_MESSAGE_MAP()
afx_msg void OnLButtonDown(UINT nFlags, CPoint point) {
DestroyWindow();
}
afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) {
DestroyWindow();
}
afx_msg void OnDestroy() {
if(m_AnimationTimerId != UINT(-1)) {
KillTimer(m_AnimationTimerId);
}
if(m_ExpireTimerId != UINT(-1)) {
KillTimer(m_ExpireTimerId);
}
if(m_DismissCallback) {
m_DismissCallback();
}
CWnd::OnDestroy();
}
afx_msg void OnTimer(UINT nIDEvent) {
if(nIDEvent == m_AnimationTimerId) {
if(++m_CurFrameIndex >= m_FrameCount) {
m_CurFrameIndex = 0;
}
DrawCurFrame();
KillTimer(m_AnimationTimerId);
m_AnimationTimerId = SetTimer(1, m_FrameDelays[m_CurFrameIndex], 0);
return;
}
if(nIDEvent == m_ExpireTimerId) {
DestroyWindow();
return;
} }
void PostNcDestroy() {
if(m_DeleteSelf) {
delete this;
}
}
void DrawCurFrame() {
Gdiplus::Graphics g(m_hWnd);
GUID dim_select_id = Gdiplus::FrameDimensionTime;
m_pImage->SelectActiveFrame(&dim_select_id, m_CurFrameIndex);
g.DrawImage(m_pImage, 0, 0, m_WindowRect.Width(), m_WindowRect.Height());
}
public:
// set m_DeleteSelf to true if a SplashWnd is created with new, and you want it to
// auto-delete itself when the window expires or is dismissed.
bool m_DeleteSelf;
// file_path the gif file path
// ExpireMs the time, in milliseconds until the window automatically closes itself
// WidthFactor the fraction of the width of the primary display to use as the splash screen's width
// HeightFactor the fraction of the height of the primary display to use as the height
// If WidthFactor or HeightFactor are 0, the original image aspect ratio is preserved
// If both are 0, the original image size, in pixels is used
SplashWnd(CString file_path, DWORD ExpireMs=2000, double WidthFactor=0.4, double HeightFactor=0) {
GdiPlusInit();
m_pImage = new Gdiplus::Image(file_path);
// Set up an array of frame times for animated images
UINT dimension_count = m_pImage->GetFrameDimensionsCount();
GUID dimension_id;
m_pImage->GetFrameDimensionsList(&dimension_id, 1);
m_FrameCount = m_pImage->GetFrameCount(&dimension_id);
UINT frame_delay_size = m_pImage->GetPropertyItemSize(PropertyTagFrameDelay);
m_FrameDelayData = new unsigned char[frame_delay_size];
Gdiplus::PropertyItem* frame_delay_item = reinterpret_cast<Gdiplus::PropertyItem*>(m_FrameDelayData);
m_pImage->GetPropertyItem(PropertyTagFrameDelay, frame_delay_size, frame_delay_item);
m_FrameDelays = reinterpret_cast<const UINT*>(frame_delay_item->value);
// Figure out the size and location of the splash window
int primary_width = GetSystemMetrics(SM_CXFULLSCREEN);
int primary_height = GetSystemMetrics(SM_CYFULLSCREEN);
int splash_width = int(primary_width * WidthFactor);
int splash_height = int(primary_height * HeightFactor);
if(splash_width == 0) {
if(splash_height == 0) {
splash_width = m_pImage->GetWidth();
splash_height = m_pImage->GetHeight();
} else {
splash_width = primary_width * splash_height / primary_height;
}
} else if(splash_height == 0) {
splash_height = primary_height * splash_width / primary_width;
}
int l = (primary_width - splash_width) / 2;
int t = (primary_height - splash_height) / 2;
int r = l + splash_width;
int b = t + splash_height;
m_WindowRect.SetRect(
(primary_width - splash_width) / 2,
(primary_height - splash_height) / 2,
(primary_width + splash_width) / 2,
(primary_height + splash_height) / 2);
// WS_EX_TOPMOST makes the window cover up other, regular windows
// WS_EX_TOOLWINDOW prevents an icon for this window in the taskbar
// WS_POPUP prevents caption and border from being drawn
CreateEx(WS_EX_TOPMOST | WS_EX_TOOLWINDOW, WindowClass(), _T("Splash"), WS_VISIBLE | WS_POPUP, m_WindowRect, 0, 0);
// Show the first frame
m_CurFrameIndex = 0;
DrawCurFrame();
// Set up the frame-flipping animation timer
m_ExpireTimerId = m_AnimationTimerId = UINT(-1);
if(m_FrameCount > 1) {
m_AnimationTimerId = SetTimer(1, m_FrameDelays[m_CurFrameIndex], 0);
}
// Set up the expiration timer
if(ExpireMs != INFINITE) {
m_ExpireTimerId = SetTimer(2, ExpireMs, 0);
}
m_DeleteSelf = false;
}
// Constructor which takes a callback function which will be called when the splash window closes
template <typename F>
SplashWnd(CString file_path, DWORD ExpireMs, double WidthFactor, double HeightFactor, F DismissCallback)
: SplashWnd(file_path, ExpireMs, WidthFactor, HeightFactor)
{
m_DismissCallback = DismissCallback;
}
~SplashWnd() {
delete [] m_FrameDelayData;
delete m_pImage;
GdiPlusRelease();
}
};
// Message map, usually in an implementation file, but here encapsulated inside the header
// using an anonymous namespace to prevent possible ODR problems.
BEGIN_MESSAGE_MAP(SplashWnd, CWnd)
ON_WM_KEYDOWN()
ON_WM_LBUTTONDOWN()
ON_WM_TIMER()
ON_WM_DESTROY()
END_MESSAGE_MAP()
}
I use the following structure to get new width and height of the resized SDL window:
if (sdl_set->GetMainEvent()->type == SDL_WINDOWEVENT)
{
if (sdl_set->GetMainEvent()->window.event == SDL_WINDOWEVENT_RESIZED)
{
ScreenWidth = sdl_set->GetMainEvent()->window.data1;
ScreenHeight = sdl_set->GetMainEvent()->window.data2;
cout << "Window Resized!" << endl;
}
}
But with this structure I'm only able to get new data after the resizing is done that is when I finish dragging and release the mouse button.
How can I get the new data continuously, that is while I'm dragging the window?
static int resizingEventWatcher(void* data, SDL_Event* event) {
if (event->type == SDL_WINDOWEVENT &&
event->window.event == SDL_WINDOWEVENT_RESIZED) {
SDL_Window* win = SDL_GetWindowFromID(event->window.windowID);
if (win == (SDL_Window*)data) {
printf("resizing.....\n");
}
}
return 0;
}
int main() {
SDL_Window* win = ...
...
SDL_AddEventWatch(resizingEventWatcher, win);
...
}
use SDL's EventWatch can resolve it.
If you are on windows, have you tried using the windows api?
I know its not a real fix but if you are not making a cross platform application, you should give it a shot.
Use HWND to find SDL's window and return the window size.
I' m new with MFC. I needed to create a floating toolbar (CToolBar) with no option of docking and save and restore its last pos.
The toolbar also should be active all the time, but its NOT.
When I'm openning a new child window (dialog for instance) from the mainframe, the floating tool bar become not active (I can not click on its buttons, or drag it etc..).
In the past I've used CDiaolog with Overlapped style and it was floating and always active as I needed. Is it possible to do the same with my Floating Toolbar? Thanks
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
toolbarIconSize.cx = toolbarIconSize.cy = TOOLBAR_MAIN_ICON_SIZE;
if ( !m_wndMyFloatingToolbar.Create(this,m_wndMyFloatingToolbar.GetBarStyle() |WS_EX_PALETTEWINDOW | WS_EX_TOPMOST |CBRS_FLOATING | WS_VISIBLE) ||
!m_wndMyFloatingToolbar.LoadToolBar(IDR_GENERAL_TOOLBAR, toolbarIconSize))
{
TRACE0("Failed to create My Floating Toolbar\n");
return -1; // fail to create
}
m_wndMyFloatingToolbar.EnableDocking(0);
EnableDocking(0);
if (!CreateCtrlBar())
{
TRACE0("Failed to create ctrl toolbar\n");
return -1; // fail to create
}
// ...
//...
return 0;
}
void CMainFrame::OnViewToolBar()
{
// ...
//...
CPoint Pos = MyFloatingToolbarGetLastPosition(); \\Get last pos
FloatControlBar( &m_wndMyFloatingToolbar, Pos, CBRS_ALIGN_LEFT );
MyFloatingToolbarSetIsVisible();
FloatControlBar( &m_wndMyFloatingToolbar, Pos, CBRS_ALIGN_LEFT );
}
void CMainFrame::MyFloatingToolbarSetIsVisible()
{
WINDOWPLACEMENT wp;
m_wndMyFloatingToolbar.GetParent()->GetParent()->GetWindowPlacement(&wp);
wp.showCmd = SW_SHOW;
m_wndMyFloatingToolbar.GetParent()->GetParent()->SetWindowPlacement(&wp);
m_wndMyFloatingToolbar.GetParent()->GetWindowPlacement(&wp);
wp.showCmd = SW_SHOW;
m_wndMyFloatingToolbar.GetParent()->SetWindowPlacement(&wp);
m_wndMyFloatingToolbar.GetWindowPlacement(&wp);
wp.showCmd = SW_SHOW;
m_wndMyFloatingToolbar.SetWindowPlacement(&wp);
}
void CWJToolBar::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)
{
CToolBar::OnWindowPosChanging(lpwndpos);
if ( GetBarStyle() & CBRS_FLOATING )
{
if((lpwndpos->flags & SWP_HIDEWINDOW) && ((this->GetParentFrame())->m_hWnd !=(this->GetTopLevelFrame())->m_hWnd))
{
CMainFrame* mf = (CMainFrame*)(AfxGetApp()->GetMainWnd());
mf->MyFloatingToolbarSavePosition();
}
}
}
You may need to debug to view its coordinates if they are correctly set. Be independent. :p
Based on your current posted code, I don't see the point of your stored data, try this
hiding your toolbar
saving its position data
changing your parent windows position and
reloading your saved coordinates.
The saved data becomes incorrect values then.
I suggest you capture the position to which you want to add your toolbar live . This makes your toolbar application more generic.
So,
Save your toolbar's i.e top-left distance to its parent windows, not its coordinates
Get your parent windows coordinates
Reload your toolbar based on the saved distance
There are of course other ways to do this but I think this is more trivial to accomplish what you may be looking for.
Use CMFCToolBar (instead CToolBar), then you need only 2 commands, to achieve this.
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CMDIFrameWndEx::OnCreate(lpCreateStruct) == -1)
return -1;
:
m_wndToolBar.SetPermament(TRUE); // it removes CloseButton (=always active)
CRect rect;
GetClientRect(&rect);
ClientToScreen(rect);
rect.OffsetRect(100, 20);
m_wndToolBar.FloatPane(rect); // Float and move it to your wished coordinates
:
}
This question is a follow up of my previous question.
First thanks for the links and examples, they do work voor a CMDIChildWnd derived CChildFrame class, but not for a CMDIChildWndEx derived one.
What i want to do:
I want to create a toolbar in the CChildFrame window (derived from CMDIChildWndEx !!)
What i have done so far:
1) Created a MDI Tabbed documents CView project using VS2008Pro App-wizard.
2) In CChildFrame i added OnCreate()
int CChildFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CMDIChildWndEx::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
if (!m_wndToolBar.Create(this) ||
!m_wndToolBar.LoadToolBar(IDR_CHILDFRAME))
{
TRACE0("Failed to create toolbar\n");
return -1; // fail to create
}
// TODO: Remove this if you don't want tool tips or a
// resizeable toolbar
m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() |
CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
// TODO: Delete these three lines if you don't want the toolbar
// to be dockable
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndToolBar); // Goes wrong here !!
return 0;
}
it compiles and runs and halts into an ASSERT in winfrm2.cpp (line
92) :
void CFrameWnd::DockControlBar(CControlBar* pBar, CDockBar* pDockBar,
LPCRECT lpRect)
{
ENSURE_ARG(pBar != NULL);
// make sure CControlBar::EnableDocking has been called
ASSERT(pBar->m_pDockContext != NULL);
if (pDockBar == NULL)
{
for (int i = 0; i < 4; i++)
{
if ((dwDockBarMap[i][1] & CBRS_ALIGN_ANY) ==
(pBar->m_dwStyle & CBRS_ALIGN_ANY))
{
pDockBar = (CDockBar*)GetControlBar(dwDockBarMap[i][0]);
/* --------> goes wrong here ------> */ ASSERT(pDockBar != NULL);
// assert fails when initial CBRS_ of bar does not
// match available docking sites, as set by EnableDocking()
break;
}
}
}
ENSURE_ARG(pDockBar != NULL);
ASSERT(m_listControlBars.Find(pBar) != NULL);
ASSERT(pBar->m_pDockSite == this);
// if this assertion occurred it is because the parent of pBar was
not initially
// this CFrameWnd when pBar's OnCreate was called
// i.e. this control bar should have been created with a different
parent initially
pDockBar->DockControlBar(pBar, lpRect);
}
in line 92 :
ASSERT(pDockBar != NULL);
// assert fails when initial CBRS_ of bar does not
// match available docking sites, as set by EnableDocking()
the source here even gives some explanation of what goes wrong here
but i dont know how to match 'initial CBRS_ of bar with those set by
EnableDocking()''
Does this even work for a CMDIChildWndEx derived CChildFrame class ?
Well so my question is does any one know how to add a toolbar to a
CMDIChildWndEx derived CChildFrame class ?
Any suggestions on how to get this working ?
My project is here :
http://www.4shared.com/file/235762968/49b8b97a/GUI50.html
Any help would be greatly appreciated !
This seems to work for a CMFCToolBar
int CChildFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CMDIChildWndEx::OnCreate(lpCreateStruct) == -1)
return -1;
m_wndToolBar.Create(this, AFX_DEFAULT_TOOLBAR_STYLE, IDR_CHILDFRAME);
m_wndToolBar.LoadToolBar(IDR_CHILDFRAME, 0, 0, TRUE );
m_wndToolBar.SetPaneStyle( CBRS_TOOLTIPS | CBRS_FLYBY| CBRS_BOTTOM);
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockPane(&m_wndToolBar);
return 0;
}
You should set m_bEnableFloatingBars = TRUE in MDIChild constructor. Without this your toolbar will no be docked by mouse, only static docking.