|
I am not familiar with the WTL. How ever to handle the selection change notification you should add following things in your code.
1. In the message map entry add a handler like..
NOTIFY_HANDLER( IDC_TREE1, TVN_SELCHANGED , OnSelChange )
2. Add a function called OnSelChange in the dialog class as below
LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled)
3. And in that function cast the pnmh to NMTREEVIEW*
NMTREEVIEW* pNMTreeView = (NMTREEVIEW*)pnmh;
HTREEITEM hSelectedItem = pNMTreeView->itemNew.hItem;
|
|
|
|
|
Hi Nave,
Thanks for the answer I have successfully made the function and made it run. I just wonder how it will give me what is highlighted among the tails? the itemNew has:
UINT mask;
HTREEITEM hItem;
UINT state;
UINT stateMask;
LPSTR pszText;
int cchTextMax;
int iImage;
int iSelectedImage;
int cChildren;
LPARAM lParam;
However even the pszText does not contain the highlighted text? even the iSelectedImage does not have the imageindex number?
Please advise
thanks,
Jayjay
|
|
|
|
|
Only the mask, hItem, state, and lParam members of these structures are valid. So if you want to get the text of the selected item, call CTreeCtrl::GetItemText() function with hItem in the structure.
|
|
|
|
|
Nave,
thank I get it now however when I use getitemtext() it only gives me a part of the string. Should I use string?
for example the item is NewItemNumber 4.23.89.15, it will only get "ber 4.23.89.15", What should I change here?
string A;
DWORD Size, BufferSize;
BufferSize = MAXBYTES;
PPERF_DATA_BLOCK PerfData = (PPERF_DATA_BLOCK) malloc( BufferSize );
Size = BufferSize;
UpdateList.GetItemText(Select, LPTSTR(&A), Size);
Thanks,
Jayjay
|
|
|
|
|
you should not use string.
modify its as
TCHAR tcItemText[MAXBYTES];
UpdateList.GetItemText(Select, tcItemText, MAXBYTES );
|
|
|
|
|
As has been said, the notify struct gives you a HTREEITEM of the newly selected tree item.
The following code may be useful to you. If the 3rd child of the 2 root item is selected, it returns a DWORD array of 2,3 - making it easier to map HTREEITEMS to your own data.
Alternatively, you can attach an lParam to each tree item also.
Iain.
typedef CDWordArray TreeStack;
BOOL CUITreeCtrl::uiGetChildNumberStack (HTREEITEM hItem, TreeStack &stack)
{
stack.SetSize (0);
while (hItem)
{
stack.InsertAt (0, uiGetChildNumber (hItem));
hItem = GetParentItem (hItem);
}
return TRUE;
}
int CUITreeCtrl::uiGetChildNumber (HTREEITEM hItem)
{
if (!hItem)
return -1;
HTREEITEM hSibling = hItem;
while (GetPrevSiblingItem (hSibling))
hSibling = GetPrevSiblingItem (hSibling);
int n = 0;
while (hSibling && hSibling != hItem)
{
n++;
hSibling = GetNextSiblingItem (hSibling);
}
return hSibling ? n : -1;
}
Plz sir... CPallini CPallini abuz drugz, plz plz help urgent.
|
|
|
|
|
Hello all,
While working on an ungraded project for class I came accross a LNK2005 Error which while I have been able to work around, I would like to know how to do it correctly.
The project is to create an employee data base that has an employee class with child classes. That's the jest of the project.
Employee - base class
-Researcher - child class
-Engineer - child class
-Manager - child class
Now the above four classes all include employee_template.h which defines a template function called void _getInput(std::string& message, T& result). Now the file containing function _getInput include stream_flush.h. Inside of stream_flush includes a function called flush_stream.
The problem I am running into is that Employee and it's three child classes all include "employee_template.h" to get the function _getInput which include stream_flush.h to get the function flush_stream which is what generates the errors.
engineer.obj : error LNK2005: "void __cdecl flush_istream(...) already defined in employee.obj
I was able to get around the error by using the linker command line option: /FORCE:MULTIPLE but I am assuming this is not the right way.
|
|
|
|
|
|
No, all the header files have #include guards, which is part of my confusion as I thought they were suppose to stop this kind of thing from happening.
|
|
|
|
|
Rizean wrote: Employee and it's three child classes all include "employee_template.h"
They just include the same header file or they all derive from a class in employee_template.h?
What does the code look like in employee.h and employee_template.h?
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
employee_template.h
#ifndef EMPLOYEE_TEMPLATE
#define EMPLOYEE_TEMPLATE
#include <iostream>
#include <string>
#include "stream_flush.h"
template <class T>
void _getInput(const std::string& message, T& result)
{
std::cout << message;
std::cin >> result;
flush_istream(std::cin);
if (std::cin.fail())
{
std::cin.clear();
std::cout << "Invalid input!\n";
_getInput<t>(message, result);
}
}
#endif
</t>
employee.h Just defines the base class and does not include employee_template.h however employee.ccp does.
employee.ccp
#include "employee.h"
#include <string>
#include "employee_template.h"
using namespace std;
Employee::Employee()
{
_getInput<string>("Please enter the employees first name: ", mFName);
}
}
researcher.h
#ifndef RESEARCHER_H
#define RESEARCHER_H
#include "employee.h"
#include <string>
#include <fstream>
class Researcher: public Employee
{
public:
Researcher();
Researcher();
};
#endif
researcher.cpp
#include "researcher.h"
#include <string>
#include <fstream>
#include "employee_template.h"
using namespace std;
Researcher::Researcher():Employee
{
_getInput<string>("Enter the researcgers school: ", mSchool);
}
};
I hope this helps and if you need more let me know. BTW, is there a way to cut and paste on Codeproject?
Edit: Errors from learning to post on CP...
|
|
|
|
|
What and where is "flush_istream" (since that's the one causing the error)?
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
One of my instructors finally got back with me and explained to me what I was doing wrong. "flush_istream" was a function I created to deal with invalid user inputs to cin calls. The function is only five lines long and it is used by a number of other functions. I placed it in its own header files stream_flush.h, but because it was the only function and because it was so short I did not separate the definition and implementation, i.e. no stream_flush.cpp file. However, as you have probably already figured out this caused the error of it being defined multiable times. My instructor suggested I inline the function which did fix the problem, however I'm thinking it would be better to separate the definition and the implementation.
#ifndef STREAM_FLUSH_H
#define STREAM_FLUSH_H
#include <istream>
inline void flush_istream(std::istream& in)
{
while(in.peak() != '\n')
in.get();
}
#endif
Thanks all for your help. Being in Korea often leaves me sitting here for up to a day or more sometimes waiting for help. Just one of the challenges of being in the Air Force and going to school online.
|
|
|
|
|
I'm writing a class named PlayerDataVector that contains an array of pointers to PlayerData objects (player_data_array is the pointer to the array), but theres a problem when i need to create a new larger array:
Why does the line "delete [] player_data_array;" give a Debug Error "HEAP CORRUPTION DETECTED: AFTER NORMAL BLOCK (#70) at ..."?
void PlayerDataVector::CreateAndCopyToNewArray(){
int current_array_size2 = current_array_size + 4;
PlayerData **new_player_data_array = new PlayerData*[current_array_size2];
int i;
for (i = 0; i < current_array_size; i++){
new_player_data_array[i] = player_data_array[i];
}
//PointToNULL(player_data_array, 0, current_array_size);
delete [] player_data_array;
player_data_array = new_player_data_array;
FillWithNULL(player_data_array, current_array_size, current_array_size2);
current_array_size = current_array_size2;
}
|
|
|
|
|
Are you writing past the bounds of the array somewhere else in your code?
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
No. player_data_array is the only pointer to the array and after the CreateAndCopyToNewArray() function has been used it points to the new array.
If I remove "delete [] player_data_array;" everything works but of course there will be an array with no pointer to it.
|
|
|
|
|
Is player_data_array initialized to NULL before the first time
CreateAndCopyToNewArray() is called?
current_array_size should be initialized too.
Otherwise, I don't see anything there that would corrupt the heap.
Mark
Mark Salsbery
Microsoft MVP - Visual C++
modified on Sunday, June 29, 2008 4:24 PM
|
|
|
|
|
From the constructor:
current_array_size = USERID_MAX_SIZE_INIT + 1;//16;
player_data_array = new PlayerData*[current_array_size];
|
|
|
|
|
hmm beats me. Can you post a short sample that fails?
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
I have tried to recreate the problem in a little program that uses PlayerDataVector. But when I do that it has no problems with PlayerDataVector (the problem is when I use it in a Metamod:source plugin).
|
|
|
|
|
Someone somewhere is trashing the heap
Looks like a debugging project!
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
If I was a betting man I'd say you are. The heap doesn't corrupt itself!
Steve
|
|
|
|
|
I am experimenting with detours from Microsoft (http://research.microsoft.com/sn/detours/). I compile this to a DLL and inject the DLL into NOTEPAD.exe. I've tried both a static and dynamic injection. I am attempting to hook the MessageBox API. When loading up notepad when injected, the first MessageBox routine (before being hooked) gives an error (The application failed to initialize properly (0xc0000005)).
To test the that actual detours stuff is working, I made a console application instead of a DLL and ran the exact same code & the message box hook works.
As another sanity check, I completely removed the MessageBox hook and simple tried to call the MessageBox API from withing the injected DLL. I still get the same error.
Does anyone know when I can't call the API from a DLL but from a console application it works fine?
Below is my code:
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <detours.h>
#include <string.h>
static int (WINAPI* winMessageBox)(
HWND hWnd,
LPCTSTR lpText,
LPCTSTR lpCaption,
UINT uType) = MessageBox;
int WINAPI __stdcall hookedMessageBox(
HWND hWnd,
LPCTSTR lpText,
LPCTSTR lpCaption,
UINT uType) {
return winMessageBox(hWnd, "This is a hooked message box!", "My Caption", uType);
}
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH:
MessageBox(NULL, "About to hook it", "HOOK STATUS", MB_OK);
DetourRestoreAfterWith();
DetourTransactionBegin();
DetourAttach(&(PVOID&)winMessageBox, hookedMessageBox);
DetourUpdateThread(GetCurrentThread());
DetourTransactionCommit();
MessageBox(NULL, "Function hooked!", "HOOK STATUS", MB_OK);
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach(&(PVOID&)winMessageBox, hookedMessageBox);
DetourTransactionCommit();
MessageBox(NULL, "Clearing hook!", "HOOK STATUS",MB_OK);
break;
}
return TRUE;
}
</string.h></detours.h></stdio.h></windows.h>
|
|
|
|
|
I also have the same problem, same context, almost the same app actually, any ideas why this cant be done?
|
|
|
|
|
Turns out that it wasn't my code. It was an issue with the Detours injection utility. I used a freeware DLL injector from the web, and it worked just fine.
|
|
|
|