|
Probably I didn't get you, but if you have to maintain the client aree content and restore it after window minimization, then you should keep all necessary data and provide the function to repaint (based on such data) inside the OnPaint method (i.e. an hardcopy of the screen content doesn't appear a good solution to me).
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
Could you suggest a better method?
Also please look at my "sort of" solution attached to the next post... Thanks alot for your time.
Terry S.
|
|
|
|
|
I looked at the call-stack debug window while stepping through the code starting just before and and up to the CClientDC dc(this); call. At the time the "Debug assertion" error is posted the stack-call window goes blank, I can trace all the way up to the error.
|
|
|
|
|
Which window are you creating inside constructor? It is not a good idea to create a window before the object is fully initialized. Constructor is called when you create an object. Once object is created, then you should create a window.
CWnd* obj = new CWnd();
obj.Create(..);
obj.paint(..);
Read about CFrameWnd [^here^]
My guess is you are getting assert at CClientDC dc(this); because 'this' does not point to a valid window because your Create function never succeeded.
In wizard generated code, do you see CSingleDocTemplate object being created anywhere? may be in InitInstance? If yes, then read about that function on msdn. it's the place where view, frame etc are created. You can put a breakpoint in framewnd c'tor and before CSingleDocTemplate.
Having said all that, as far as I have understood your problem, you just need to do this:
In your wizard generated view class, create a CString variable "CString m_strText;"
in your CMyView constructor, put m_strText = "Hello";
and inside your CMyView::OnDraw, draw the text to screen.
pDC->DrawText(m_strText, ....);
Hope any of this makes sense to you,
|
|
|
|
|
 Maybe you didn't get my phsyco babble but the previous code works perfectly as long the application is created manually using the method shown. The only portion of code that I'm trying to use is the code under "Virtual Window Stuff" the Create function in that is working fine if not I wouldn't get a window.
My problem is with App-Wizard generated MFC single document application. However I have a kind-of-solution but for what ever reason the background of the view goes black so I have to change the text color and text background. Not quite what I'm after yet.
Check out the code below it works quite well.
I think this is how it works;
A bitmsap is created to hold the content of the device context.
draw stuff is added to the bitmap in memory then pasted to the view when I call ShowIt().
I had to use a message handler or other function to create the "virtual window" (memory DC). The problem is It doesn't stick around like this I have try and keep everything in the bitmap and recreate the memory DC each time before I draw.
Source File Stuff
void Ccom_testView::OnLButtonDblClk(UINT nFlags, CPoint point)
{
maxX = GetSystemMetrics(SM_CXSCREEN);
maxY = GetSystemMetrics(SM_CYSCREEN);
CClientDC dc(this);
memDC.CreateCompatibleDC(&dc);
if (m_bmp.m_hObject == NULL)
m_bmp.CreateCompatibleBitmap(&dc, maxX, maxY);
memDC.SelectObject(&m_bmp);
bkBrush.CreateStockObject(WHITE_BRUSH);
memDC.SelectObject(&bkBrush);
CBitmap* pOldBitmap = memDC.SelectObject(&m_bmp);
CBrush* pOldbkBrush = memDC.SelectObject(&bkBrush);
memDC.SetTextColor(RGB(0, 200, 100));
memDC.SetBkColor(RGB(0,0,0));
wsprintf(str, "Hello World");
memDC.TextOutA(point.x, point.y, str, strlen(str));
memDC.SelectObject(pOldbkBrush);
memDC.SelectObject(pOldBitmap);
memDC.DeleteDC();
ShowIt();
CView::OnLButtonDblClk(nFlags, point);
}
void Ccom_testView::OnPaint()
{
CPaintDC dc(this);
ShowIt();
}
bool Ccom_testView::ShowIt(void)
{
CClientDC dc(this);
CBitmap* pbmOld = NULL;
memDC.CreateCompatibleDC(&dc);
pbmOld = memDC.SelectObject(&m_bmp);
dc.BitBlt(0, 0, maxX, maxY, &memDC, 0, 0, SRCCOPY);
memDC.SelectObject(pbmOld);
memDC.DeleteDC();
return false;
}
Header File Stuff
class Ccom_testView : public CView
{
public:
CDC memDC;
CBrush bkBrush;
CBitmap m_bmp;
CFont m_SystemFont, m_AnsiVarFont;
protected:
Ccom_testView();
DECLARE_DYNCREATE(Ccom_testView)
public:
Ccom_testDoc* GetDocument() const;
public:
public:
virtual void OnDraw(CDC* pDC);
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
public:
virtual ~Ccom_testView();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
protected:
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
public:
afx_msg void OnPaint();
public:
bool ShowIt(void);
};
Comments or suggestions would be great. Even better yet a better way to do it.
Thank you for your help.
|
|
|
|
|
I am not an expert myself but you can try few changes -
Create a new bitmap everytime you create a new memdc.
bool Ccom_testView::ShowIt(void)
{
CClientDC dc(this);
CBitmap* pbmOld = NULL;
memDC.CreateCompatibleDC(&dc);
CBitmap memBmp;
memBmp.CreateCompatibleBitmap(&dc);
pbmOld = memDC.SelectObject(&membmp);
dc.BitBlt(0, 0, maxX, maxY, &memDC, 0, 0, SRCCOPY);
memDC.SelectObject(pbmOld);
memBmp.DeleteObject();
memDC.DeleteDC();
return false;
}
Idont undersatnd your code in LButtonDblClk..
try to do all text out stuff etc into memDC and then simply BitBlt memDC onto CPaintDC.
All painting stuff should go inside OnPaint..
|
|
|
|
|
Basically the LButtonDblClk function is using TextOut to put "Hello World" on the screen at the cursors position. The intention is to have the output accumulate on the screen and remain on the screen when resized, minimized or covered by another window etc...
I tried recreating the bitmap each time by changing the conditional statement at the beginning of LButtonDblClk if(!= NULL)delete the bitmap and just have the bitmap created each time the problem with that is the output does not accumulate on the screen.
I will try what you have here to see if my results can improve. Again this code is working, it just paints the background black and I am having trouble figuring out why that is, I have been messing with this same project for a while, maybe I'll try generating a new one and see what happens.
I am puzzled why this is so difficult to solve, although I have not written alot of code I have been doing it for a long time and the programmer has always had to take care of refreshing the screen and keeping the output(text, graphics etc..) on there theirself, at least I have. So what does a novice have to do to get the information or at least a clue to the solution. This cannot be stumping the programming gurus here in this forum, no way.
Thanks again
Terry S.
|
|
|
|
|
So what you intend to do is (correct if I'm wrong):
When user double clicks the left mouse button, draw some graphics and make it permanent.
If I guessed well then you have to:
- Properly erase the background (see [^]).
- Make your painting function (i.e.
ShowIt() ) accepting as argument, a CPaintDC instead of creating its own device context. - Never call directly your paint function (or other drawing code, use instead
InvalidateRect and UpdateWindow to force the painting happen). - inside the button handler just set a flag (a member variable of the class) and use it to conditionally call your painting function inside
OnPaint
For instance:
void Ccom_testView::OnLButtonDblClk(UINT nFlags, CPoint point)
{
m_showit=true;
InvalidateRect(NULL);
UpdateWindow();
}
void Ccom_testView::OnPaint()
{
CPaintDC dc(this);
if (m_showit)
ShowIt(dc);
}
void Ccom_testView::ShowIt(CPaintDC & dc)
{
}
Hope it eventually makes sense.
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
Actually this makes alot of of sense, I have a better time making sense of things than I do communicating them in a way that makes sense, if that makes sense .
Seriously I think this is going to work for me once I get it implemented properly. I have always been week at passing perameters and therefore I avoid it and never think about the possibilities. I have alot to learn but I'm not going to give up.
Thank you very much for your help, I have learned a great deal just in the communications, that's asside from the code information.
Terry S.
|
|
|
|
|
I thought I had it...
Here is what I got, it all compiles and runs great but I never see anything show up on the window.
What did I do wrong or not do?
void CComViewView::OnDraw(CDC* )
{
CComViewDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
CPaintDC dc(this);
if(m_show)
ShowIt(dc);
}
void CComViewView::OnLButtonDblClk(UINT nFlags, CPoint point)
{
pos = point;
m_show = true;
m_userIn = true;
InvalidateRect(NULL);
UpdateWindow();
CView::OnLButtonDblClk(nFlags, point);
}
void CComViewView::ShowIt(CPaintDC & dc)
{
if(!m_userIn)return;
maxX = GetSystemMetrics(SM_CXSCREEN);
maxY = GetSystemMetrics(SM_CYSCREEN);
CDC memDC;
CBitmap m_bmp;
memDC.CreateCompatibleDC(&dc);
m_bmp.CreateCompatibleBitmap(&dc, maxX, maxY);
memDC.SelectObject(&m_bmp);
memDC.SetTextColor(RGB(0, 200, 100));
memDC.SetBkColor(RGB(0,0,0));
wsprintf(str, "Hello World");
memDC.TextOutA(pos.x, pos.y, str, strlen(str));
memDC.BitBlt(0, 0, maxX, maxY, &memDC, 0, 0, SRCCOPY);
UpdateWindow();
m_userIn = false;
}
|
|
|
|
|
SimplCodr wrote:
void CComViewView::OnDraw(CDC* /*pDC*/)
{
CComViewDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// TODO: add draw code for native data here
CPaintDC dc(this);
if(m_show)
ShowIt(dc);
}
You don't need to create a new dc, change to (note I uncommented the pDC argument)
void CComViewView::OnDraw(CDC* pDC)
{
CComViewDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
if(m_show)
ShowIt(*pDC);
}
SimplCodr wrote: memDC.BitBlt(0, 0, maxX, maxY, &memDC, 0, 0, SRCCOPY);
This is the mistake, change to
dc.BitBlt(0, 0, maxX, maxY, &memDC, 0, 0, SRCCOPY);
You've to work on the background, there are still some flaws, but it is much better now.
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
Excellent, I think I have everything I will need I just need to plug away at it for a while before I come crying for more help. Thanks a bunch. 
|
|
|
|
|
You are welcome.
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
Try [^vc++ in 21 days^] It will give you very good idea of mfc in 2 or 3 days. it's the shortest and most effective way known to me to learn about mfc. it may be a bit dated but the concepts are same and you don't need to spend big bucks to purchase it from nearby second hand bookshop or if you are really smart, you can find an ebook floating around somewhere in this cyberspace. (i know no one likes to spend money on buying fat and boring technical books)
.. and i hope your problem is solved by now.
|
|
|
|
|
I like to learn and books are good way to start... I accually own the predecessor to that book "C++ in 21 days" which I found to be quite good. I also found "MFC From the Ground Up" which is a great book if you are compiling using Visual C++ 6.0, it seems like things are done non-stansard though, you have to change alot things around to get them to compile and run from the VS2005 that I have now. It's really a good thing Microsoft made it difficult to go back to old version of compiler, cause I would have and not learned what I have. Man and I'll tell you from A novices perspective that upgrade has caused me more pain than I ever imagined I could get from writting my simple code. I think there is a new book out something like MFC from the ground up for VS2005, if that's the case I would really like to get a copy of that.
It's people like you and Pallini that make me come here when I need help. You folks are awesome keep up the good work and thank you.
Terry S.
|
|
|
|
|
SAFEARRAY* arr;
int iRes = RestoreFactory(bstrPath, // this function is for c#com object &arr);
// Copy SAFEARRAY* values to output
int iSize;
if ( arr != NULL )
{
iSize = arr->rgsabound[0].cElements;
BYTE *byteArr = new BYTE[iSize];
for (int i = 0; i < iSize; i++)
{
byteArr[i] = ((BYTE)((( char *)(*arr).pvData)[i]));
}
}
The byteArr seems to be wrong!
Is it the right convertion???
Thanks!
|
|
|
|
|
TalSt wrote: The byteArr seems to be wrong!
Namely?
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
TalSt wrote:
Convert BYTE* array (unmanaged) to SAFEARRAY
Is it the right convertion???
No.
The code you have posted is converting from SAFEARRAY to BYTE[]. Exactly the opposite of your post title. Can you clarify what it is you are trying to achieve?
Best Wishes,
-David Delaune
|
|
|
|
|
Hello,
Yes. You are right. The title is wrong. It should be: "converting from SAFEARRAY to BYTE[]".
Do you know if the code is correct?
Thanks! 
|
|
|
|
|
Hi TalSt,
Check out this older post [^]where I describe a unique way to build a LPCSTR from a SAFEARRAY. You could use the same technique to convert SAFEARRAY to BYTE.
Best Wishes,
-David Delaune
|
|
|
|
|
Hello everyone !
Here I want to read one of the ListCtrl datas from other process(report style),and write them into my ListCtrl.
Example this code ,I want to read the "Window Task Manager" datas(in Process Tab),and write it into my ListCtrl:
BOOL CTestDlg::OnInitDialog()
{
CDialog::OnInitDialog();
......
LONG lStyle = m_ListCtrl.SendMessage(LVM_GETEXTENDEDLISTVIEWSTYLE);
lStyle |= LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES;
m_ListCtrl.SendMessage(LVM_SETEXTENDEDLISTVIEWSTYLE, 0,(LPARAM)lStyle);
m_ListCtrl.InsertColumn(0,"Name",NULL,100, -1);
m_ListCtrl.InsertColumn(1,"PID",NULL,60,-1);
m_ListCtrl.InsertColumn(2,"User",NULL,120,-1);
m_ListCtrl.InsertColumn(3,"CPU",NULL,60,-1);
return TRUE;
}
void CTestDlg::OnBtnRead()
{
m_ListCtrl.DeleteAllItems();
HWND hWnd,hListview;
hWnd=::FindWindow(NULL,_T("Windows Task Manager"));
hWnd=::FindWindowEx(hWnd,0,"#32770",0);
hListview=::FindWindowEx(hWnd,0,_T("SysListView32"),NULL);
if(!hListview)
{
MessageBox("Listview handle is NULL !");
return;
}
int count = (int)::SendMessage(hListview,LVM_GETITEMCOUNT,0,0);
int i,nItem;
CString strTemp;
strTemp.Format("Total process :%d",count);
MessageBox(strTemp);
CString str1="";
CString str2="";
CString str3="";
CString str4="";
DWORD pid;
HANDLE process;
LVITEM lvi, *_lvi;
char firstitem[512], secitem[512],thirditem[512],fourthitem[512];
char *_firstitem, *_secitem,*_thirditem,*_fourthitem;
memset(firstitem,0,512);
memset(secitem,0,512);
memset(thirditem,0,512);
memset(fourthitem,0,512);
GetWindowThreadProcessId(hListview, &pid);
process=OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_READ|
PROCESS_VM_WRITE|PROCESS_QUERY_INFORMATION, FALSE, pid);
_lvi=(LVITEM*)VirtualAllocEx(process, NULL, sizeof(LVITEM),MEM_COMMIT, PAGE_READWRITE);
_firstitem=(char*)VirtualAllocEx(process, NULL, 512, MEM_COMMIT,PAGE_READWRITE);
_secitem =(char*)VirtualAllocEx(process, NULL, 512, MEM_COMMIT,PAGE_READWRITE);
_thirditem=(char*)VirtualAllocEx(process, NULL, 512, MEM_COMMIT,PAGE_READWRITE);
_fourthitem=(char*)VirtualAllocEx(process,NULL, 512, MEM_COMMIT,PAGE_READWRITE);
lvi.cchTextMax=512;
for(i=count; i>=0; i--)
{
lvi.iSubItem=0;
lvi.pszText=_firstitem;
WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL);
::SendMessage(hListview, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi);
lvi.iSubItem=1;
lvi.pszText=_secitem;
WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL);
::SendMessage(hListview, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi);
lvi.iSubItem=2;
lvi.pszText=_thirditem;
WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL);
::SendMessage(hListview, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi);
lvi.iSubItem=3;
lvi.pszText=_fourthitem;
WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL);
::SendMessage(hListview, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi);
ReadProcessMemory(process, _firstitem, firstitem, 512, NULL);
ReadProcessMemory(process, _secitem, secitem, 512, NULL);
ReadProcessMemory(process, _thirditem, thirditem, 512, NULL);
ReadProcessMemory(process, _fourthitem, fourthitem, 512, NULL);
str1.Format("%s",firstitem);
str2.Format("%s",secitem);
str3.Format("%s",thirditem);
str4.Format("%s",fourthitem);
nItem = m_ListCtrl.InsertItem(0,str1);
m_ListCtrl.SetItem(nItem,1,1,str2,NULL,0,0,0);
m_ListCtrl.SetItem(nItem,2,1,str3,NULL,0,0,0);
m_ListCtrl.SetItem(nItem,3,1,str4,NULL,0,0,0);
}
VirtualFreeEx(process, _lvi, 0, MEM_RELEASE);
VirtualFreeEx(process, _firstitem, 0, MEM_RELEASE);
VirtualFreeEx(process, _secitem, 0, MEM_RELEASE);
VirtualFreeEx(process, _thirditem, 0, MEM_RELEASE);
VirtualFreeEx(process, _fourthitem, 0, MEM_RELEASE);
}
but in some progrmas, when you double click one item,you can edit it as use EditBox. so I can't used the above method to read the data from the control.
How can I read them ?
|
|
|
|
|
wangningyu wrote: Example this code ,I want to read the "Window Task Manager" datas(in Process Tab),and write it into my ListCtrl:
Wouldn't it be easier to just get your own list via CreateToolhelp32Snapshot() and the Process32First() /Process32Next() pair?
"Old age is like a bank account. You withdraw later in life what you have deposited along the way." - Unknown
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
|
|
|
|
|
Sorry , I don't want the list of my processes.
that's only a SysListView32 Style Control of the sample code.
if the edit listcontrol in other programs, how can I read the list ?
modified on Thursday, October 22, 2009 12:42 PM
|
|
|
|
|
Assuming you have the window handle of the control, first send it a LVM_GETITEMCOUNT message. Then for each item, send the control a LVM_GETITEMTEXT message.
"Old age is like a bank account. You withdraw later in life what you have deposited along the way." - Unknown
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
|
|
|
|
|
this item has two windows,you can find the editbox's handle to read text from it.
|
|
|
|
|