I'm creating a message window to receive timer messages in a separate queue from the main Excel Application window. I can then subclass that window without a torrent of irrelevant stuff going through my (slow) VBA message loop.
As I understand it, I can use the hWndParent parameter along with the WM_CHILD style to make a window that is a child of the main window handle. According to the DestroyWindow docs:
If the specified window is a parent or owner window, DestroyWindow
automatically destroys the associated child or owned windows when it
destroys the parent or owner window.
So I imagine that supplying Application.hWnd as the parent would mean that when I close Excel, all the associated windows are removed too.
But Message-Only Windows need HWND_MESSAGE as the parent, so I'm not sure when/if they'll be cleared up?
FWIW, here's the code I'm using to generate/find the window (my program may lose its state so I can't rely on storing the handle in a variable)
Public Function getMessageWindow(ByVal windowName As String) As hWnd
Const className As String = "Static"
Dim result As hWnd
result = ApiFindWindow(className, windowName)
If result.value.address = 0 Then 'not found
Const HWND_MESSAGE As Long = (-3&)
result = APiCreateWindowEx(0, className, windowName, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, 0, 0)
End If
getMessageWindow = result
End Function
Related
I need to detect whether a Uiview is a standard opened view or if it is an activated viewport on a sheet. Querying the uiview’s view Id returns the Id of the activated viewport's view. I have found no direct way to detect that a uiview is actually a sheet with an activated viewport.
I am already tracking opened views in the view activated event for another purpose. So I considered storing the view Id with the uiview hashcode for later checking that it was indeed a sheetview prior to becoming an activated view. Unfortunately, and I think in opposition to standard use, the uiview hashcode is not stable. Multiple hashcode requests from the uiview object return different values.
Does anyone have a way to detect this condition? I need to be able to use the the methods on the uiview still. So any help to find the actual child windows I would like to relate to the uiview object. The view still says "Sheet: ..." in the title when a view is activated.
TaskDialog mainDialog = new TaskDialog("Hello, viewport check!");
mainDialog.MainInstruction = "Hello, viewport check!";
mainDialog.MainContent =
"Sadly Revit API doesn't automatically know if the user is in an active viewport. "
+ "Please click 'Yes' if your are, or 'No' if your not.";
mainDialog.AddCommandLink(TaskDialogCommandLinkId.CommandLink1,
"Yes, I am in an active viewport on a sheet.");
mainDialog.AddCommandLink(TaskDialogCommandLinkId.CommandLink2,
"No, I am just in an ordinary view.");
mainDialog.CommonButtons = TaskDialogCommonButtons.Close;
mainDialog.DefaultButton = TaskDialogResult.Close;
TaskDialogResult tResult = mainDialog.Show();
bool YesOrNo = true;
if (TaskDialogResult.CommandLink1 == tResult)
{
YesOrNo = true;
}
else if (TaskDialogResult.CommandLink2 == tResult)
{
YesOrNo = false;
}
else{
return;
}
You can use the ViewSheet GetAllViewports method to determine all the viewports on a given sheet. Using that, you could put together a bi-directional dictionary lookup system map any sheet to all the viewports it hosts and vice versa. That should help solve your task. Here is some example usage:
http://thebuildingcoder.typepad.com/blog/2014/04/determining-the-size-and-location-of-viewports-on-a-sheet.html
Im late to the party - but another way to sense if the user is in a viewport is to investigate the Process.MainWindow title. Something like this (in RevitPythonShell):
import threading, clr
from System.Diagnostics import Process
# need winform libraries for feedback form only
clr.AddReference("System.Windows.Forms")
from System.Windows.Forms import Form, Label
app = __revit__.Application
doc = __revit__.ActiveUIDocument.Document
ui = __revit__.ActiveUIDocument
def lookAtWindow(activeView):
# Looking for one of three conditions:
# 1. User is on a sheet (ActiveView will be DrawingSheet)
# 2. User is in an active ViewPort on a sheet (ActiveView will NOT be be DrawingSheet, but MainWindowTitle will contain " - [Sheet: " string)
# 3. User is on a View (neither of the previous two conditions)
result = False
if str(activeView.ViewType) == 'DrawingSheet':
result = 'Youre on a sheet'
else:
processes = list(Process.GetProcesses())
for process in processes:
window = process.MainWindowTitle
if window and 'Autodesk Revit '+app.VersionName[-4:] in window and ' - [Sheet: ' in window and ' - '+doc.Title+']' in window:
result = 'I reckon youre in a Viewport'
if not result:
result = 'so you must be in a '+str(activeView.ViewType)
form = Form()
form.Width = 300
form.Height = 100
label = Label()
label.Width = 280
label.Height = 70
label.Text = result
label.Parent = form
form.ShowDialog()
# need to close RevitPythonShell console before checking MainWindowTitle, so run on timer
threading.Timer(1, lookAtWindow, [ui.ActiveView]).start()
__window__.Close()
My object and it's clones(with a collider attached) are pooled and deactivated on swipe left or right. When they are activated, they immediateliy move along the direction of swipe. How can possibly set their respawn speed to zero?(horizontal movement)
I would make a script for the objects I wouldn't want to move and either attach it to each individual object or a manager based object which controls the spawned objects. You can simply after instantiating, set their speed variable to 0 and call a coroutine for x seconds and at the end of the coroutine it would change their speed variable back. Make sure each has its own variable for speed as to not affect the whole lot.
It would be something like this..
GameObject clone = (GameObject)Instantiate(prefab, new Vector3(0, 0, 0), Quaternion.identity);
// set speed to zero here.
StartCoroutine(WaitAndMove(2.0F));
And add this function
IEnumerator WaitAndMove(float waitTime) {
yield return new WaitForSeconds(waitTime);
// set speed back here
}
I've a DGRect::draw(HWND hwnd) which simply draws a Blank HBITMAP on hwnd window Handle.
I works fine If I call it from main() . It even works correctly If called from DGRDPServer::DGRDPServer() constructor which is QTcpServer Derived. It also works well from DGRDPServer::listen(qint64 port). The hwnd is passed in DGRDPServer constructor. The Problem appears when I call it from DGRDPServer::incomingConnection(int socketDescriptor) I've qDebug()ed value of hwnd and its Okay. Whats Causing the draw for failing. ??
Here goes my code for DGRect::draw(HWND hwnd)
QByteArray ba;
HDC hdc = GetWindowDC(hwnd);
HBITMAP scrn = CreateCompatibleBitmap(hdc,/*width*/200,/*height*/200);
SetBitmapBits(scrn, /*size()*/200*200*4, ba.data());
BITMAP bm;
PAINTSTRUCT ps;
HDC whdc = BeginPaint(hwnd, &ps);
HDC hdcMem = CreateCompatibleDC(whdc);
HBITMAP hbmOld = (HBITMAP)SelectObject(hdcMem, scrn);
GetObject(scrn, sizeof(bm), &bm);
BitBlt(whdc, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
SelectObject(hdcMem, hbmOld);
DeleteDC(hdcMem);
EndPaint(hwnd, &ps);
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
Update
Seems like hwnd can be painted from main thread only. However UpdateWindow Call works from a different thread. and looks like functions like DGRDPServer::incomingConnection(int socketDescriptor) are called from a different thread. So What can be done to paint hwnd from a different thread ?
My guess is that the problem here is your use of BeginPaint: as per docs: An application should not call BeginPaint except in response to a WM_PAINT message
Outside of that, you may be able to use plain GetDC/ReleaseDC instead of BeginPaint/EndPaint pair.
The 'windows way' of doing this sort of thing, however, is to just use the worker thread to update the internal data appropriately, and then use InvalidateRect or similar to tell Windows that the window needs to be updated, and Windows will send a WM_PAINT later. UpdateWindow is essentially a more immediate version of this: it sends WM_PAINT to the window right there and then (which causes the actual painting to take place on that hwnd's thread).
I have an MDI MFC FEATURE PACK app in vs2008.
I do need to determine what child window(s) are visible , even if multiple tab groups are created by the user, and also what is the last activated MDI child. I have found that in my mainframe CMDIFrameWndEx class, the methods
m_wndClientArea.FindActiveTabWnd ();
m_wndClientArea.GetFirstTabWnd ();
m_wndClientArea.GetNextTabWnd ();
that could potentially let me navigate through all tab grops. Trouble is that these methods return an CMFCTabControl that does not offer any method/member to obtain an pointer to the MDI child windows in the tab. It only gives the index of the active tab.
So how do I get the CMDIChildWndEx* pointer of the "in front" window of the given tabgroup?
Because your CMDIChildWndEx instances are wrapped in a tab control wrapper you can get the active tab and then the wnd from that, e.g.
int nActive = pTabCtrl->GetActiveTab();
CWnd * pWnd = pTabCtrl->GetTabWndNoWrapper( nActive );
CMDIChildWndEx * pChild = dynamic_cast<CMDIChildWndEx*>(pWnd);
It was wonderful to find this code - exactly what I needed to redraw my active tab windows in each tab group since with multiple (split) tab groups, they were not being redrawn correctly. However, to make the loop work I had to do the following (CChildFrame is my derived frame type):
m_arrpActiveChilds.RemoveAll ();
const CObList& TabGroups =m_wndClientArea.GetMDITabGroups();
if (TabGroups.GetCount ()>0) {
POSITION crtPos = TabGroups.GetHeadPosition ();
CMFCTabCtrl* pCrtTabCtrl;
do {
pCrtTabCtrl=DYNAMIC_DOWNCAST(CMFCTabCtrl, TabGroups.GetNext(crtPos));
int nActive = pCrtTabCtrl->GetActiveTab();
CWnd * pWnd = pCrtTabCtrl->GetTabWndNoWrapper( nActive );
CChildFrame * pChild = dynamic_cast<CChildFrame*>(pWnd);
m_arrpActiveChilds.Add (pChild);
} while(crtPos != NULL);
I cannot figure out how to use the WebBrowser control without having it create a window in the taskbar.
I am using the IWebBrowser2 ActiveX control directly because I need to use some of the advanced features like blocking downloading JAVA/ActiveX/images etc. That apparently is not available in the WPF or winforms WebBrowser wrappers (but these wrappers do have the ability to create the control with no UI)
Here is my code for creating the control:
Type webbrowsertype = Type.GetTypeFromCLSID(Iid_Clsids.CLSID_WebBrowser, true);
m_WBWebBrowser2 = (IWebBrowser2)System.Activator.CreateInstance(webbrowsertype);
m_WBWebBrowser2.Visible = false;
m_WBOleObject = (IOleObject)m_WBWebBrowser2;
int iret = m_WBOleObject.SetClientSite(this);
iret = m_WBOleObject.SetHostNames("me", string.Empty);
tagRECT rect = new tagRECT(0, 0, 0, 0);
tagMSG nullMsg = new tagMSG();
m_WBOleInPlaceObject = (IOleInPlaceObject)m_WBWebBrowser2;
//INPLACEACTIVATE the WB
iret = m_WBOleObject.DoVerb((int)OLEDOVERB.OLEIVERB_INPLACEACTIVATE,
ref nullMsg, this, 0, IntPtr.Zero, ref rect);
IConnectionPointContainer cpCont = (IConnectionPointContainer)m_WBWebBrowser2;
Guid guid = typeof(DWebBrowserEvents2).GUID;
IConnectionPoint m_WBConnectionPoint = null;
cpCont.FindConnectionPoint(ref guid, out m_WBConnectionPoint);
m_WBConnectionPoint.Advise(this, out m_dwCookie);
This code works perfectly but it shows a window in the taskbar. If i omit the DoVerb(OLEDOVERB.OLEIVERB_INPLACEACTIVATE) call, then Navigating to a webpage is not working properly. Navigate() will not download everything on the page and it never fires the DocumentComplete event. If I add a DoVerb(OLEIVERB_HIDE) then I get the same behavior as if I omitted the DoVerb(OLEDOVERB.OLEIVERB_INPLACEACTIVATE) call.
This seems like a pretty basic question but I couldn't find any examples anywhere.
Check the wraparounds in BUG: DocumentComplete Does Not Fire When WebBrowser Is Not Visible