Maximus5 / conemu-inside

An example, how to embed http://conemu.github.io/ into another graphical application
57 stars 42 forks source link

HWND Resize in Control #13

Closed hypersw closed 8 years ago

hypersw commented 8 years ago

I give ConEmu my HWND, it creates its own one and places to dock within that HWND. Now in some cases it then would track my HWND size and update its docked state, while in some others it won't.

I'd like to know the big design here.

From one point, there's some code to discover and track resizing of the conemu child hwnd in the original C# sample.

From another point, there's a function CConEmuInside::InsideUpdatePlacement which should be called on timer and handle just this. In some cases I've observed it working (that's why I haven't put the manual resize code in the first place). But not always. What's even stranger, often it would move the terminal window and the conemu statusbar out of sync, leaving them at an awkward offset.

From yet another point, the common pattern is that you move hwnds you know, i.e. if you receive a freshly-created child HWND from some party and place it into your parent HWND, then you gotta also control its placement and all. But if you give a HWND and smth magically appears and initially docks in it, then usually it would also track its resizes as well, and you do not quite even know this HWND. That's not a hard rule but an observation of the common pattern.

Here I'm not asking for help in implementing smth, just would like to know the best / intended way it should be first.

Maximus5 commented 8 years ago

In theory, CConEmuInside::InsideUpdatePlacement is quite enough to automatically update ConEmu size. If it's not working, that's probably a bug in ConEmu, but I can't find conditions what that may happen.

In the original sample, resizing was forced just to maintain ConEmu size quicker, timer in ConEmu has an obvious even a small delay.

hypersw commented 8 years ago

Okay, here's the plot.

Status bar text is updated on timer, like this:

    ConEmu.exe!CConEmuInside::GetInsideRect(tagRECT * prWnd) Line 859   C++
    ConEmu.exe!CConEmuSize::CalcRect(ConEmuRect tWhat, CVirtualConsole * pVCon) Line 375    C++
    ConEmu.exe!CConEmuSize::GetGuiClientRect() Line 1322    C++
    ConEmu.exe!CStatus::GetStatusBarClientRect(tagRECT * rc) Line 2282  C++
    ConEmu.exe!CStatus::InvalidateStatusBar(tagRECT * rcInvalidated) Line 1051  C++
    ConEmu.exe!CStatus::UpdateStatusBar(bool abForce, bool abRepaintNow) Line 1039  C++

Here GetStatusBarClientRect is only needed to call InvalidateRect. As it comes down to GetInsideRect, it writes the current parent rect into the mrc_InsideParent field.

Now, in the InsideUpdatePlacement fn there's a check to skip updating position in case mrc_InsideParent is already up-to-date with the parent. But it is up-to-date after a call to GetStatusBarClientRect, so the resize is (almost) always skipped here.

Either it should cache and check its own field, or order the calls to status bar, or status bar should not write this field, what would be the proper way?

hypersw commented 8 years ago

(reproes for me on winforms branch, just as the ControlShowcaseForm opens initially)