[译]错误报告
By robot-v1.0
本文链接 https://www.kyfws.com/applications/bugreporter-zh/
版权声明 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
- 17 分钟阅读 - 8342 个词 阅读量 0[译]错误报告
原文地址:https://www.codeproject.com/Articles/9431/Bugreporter
原文作者:BlackDice
译文由本站 robot-v1.0 翻译
前言
A handy bug-tracking tool for software development companies.
适用于软件开发公司的方便的错误跟踪工具.
介绍(Introduction)
这是一个在软件公司内部使用的错误跟踪应用程序,我公司中的大多数人已经使用了几个月.(This is a bug-tracking application for use within a software company that most of the people in my company have been using for a couple of months now.)
背景(Background)
我开始这个项目是为了跟踪我们公司的错误并在LAN上的测试人员和程序员之间来回交流.我们已经有一个基于Web的错误跟踪工具,但实际上没有人在使用它.此外,我并不真的喜欢基于Web的软件.因此,我已经花了几个月的时间进行研究,对此我感到非常自豪.我知道其中仍然存在一些错误,还有一些可以更改以提高效率的东西(我将在下面的适当部分中进行讨论).(I started this project as a way to keep track of our company’s bugs and communicate back and forth between the testers and programmers on our LAN. We already had a web-based bug-tracking tool, but nobody was actually using it. Besides, I don’t really like web-based software for this purpose. So I’ve worked on this over a few months' time, and I’m pretty proud of it. I know there’re still a couple of bugs in it, and also some stuff that could be changed to make it more efficient (which I will discuss below in the appropriate section).)
首先,我要感谢Chris Maunder和其他CPians(First of all, I’d foremost like to thank Chris Maunder and the other CPians who have worked on the*) MFC网格控件(MFC Grid Control) .这种控制使我想做的事情变得容易得多.感谢<明镜>的作者陆明明(. This control made things a lot easier for what I was trying to do. I thank Mingming Lu, the author of the*) ‘Network renju Game’)“网络连珠游戏”( 有关处理套接字的代码的文章.我还要感谢Prateek Kaul,<(article for the code I got for dealing with sockets. I also thank Prateek Kaul, author of the*) ‘System Tray Icons’*)系统托盘图标( 我在程序中用于在系统任务栏中显示图标的类的文章.最后,但同样重要的是,我要感谢Marc Richarme,(article for the class that I use in my program for displaying the icon in the system tray. Last, but definitely not least, I’d like to thank the Marc Richarme, author of the*) ‘EasySize’*)" EasySize"( ()文章.在调整对话框大小时,他的宏非常宝贵.(() article. His macros have been invaluable in the resizing of my dialogs.)
此代码是使用Visual Studio .NET 2003和MFC的7.1版编译的,在Windows2000/XP下可以正常工作.(This code was compiled using Visual Studio .NET 2003, using version 7.1 of the MFC, and works fine under Windows2000/XP.)
(重要!!!)请先阅读((Important!!!) Please Read This First)
此代码在我们公司的服务器上使用SQL Server数据库.我已包含一个脚本((This code uses an SQL Server database on our company’s server. I have included a script ()bugreporter.sql(bugreporter.sql))重新创建您自己的数据库的所有表.我们的数据库中有一个"(未知)“条目,恰好有一个() to recreate all the tables for your own database. There is an entry in our database for ‘(unknown)’ which happens to have a) personid
在我们的数据库中为4.一些代码实际上引用了此常量值,这就是为什么我将添加到脚本中以添加这些人的原因.因此,请勿删除此记录-或相应地更改此值.表” tlkpreturnstatus"和" tlkptype"中也添加了值.表" tlkpSeverity"中有五个值.这些值与显示在网格中的标志图标相对应(只有五个).(of 4 in our database. Some of the code actually references this constant value, that’s why I’ve added to the script to add these people. So don’t delete this record – or change this value accordingly. There have also been values added to the tables ‘tlkpreturnstatus’ and ‘tlkptype’. There are five values in the table ‘tlkpSeverity’. These values correspond to the flag icons that show up in the grid (and there’re only five of them).)
我还没有包括克里斯桑德(Chris Maunder)的(*I have not included Chris Maunder's*) [MFC网格(*MFC Grid*)](http://www.codeproject.com/miscctrl/gridctrl.asp) 源,因为我用于该项目的图形和图标足够大.我也没有包括(*source, because the graphics and icons I use for this project are big enough as it is. I also have not included the*)
CSystemTray` 源文件或EasySize源文件.除了增加下载量之外,我认为所有这些文章都应该由用户下载,这样我就不会再分发其他作者的源代码.另外,我认为这些都是不错的文章,因此您可能应该自己看看!(source files, or the EasySize source files. Besides making the download bigger, I think all these articles should be downloaded by the user so that I’m not redistributing another author’s source code. Also, I think these are all good articles, so you should probably give them a look yourself!)
如果运行演示,则需要首先在SQL Server上创建的数据库中运行SQL脚本,其数据库,用户名和密码为" bugreporter".该演示的构建方式为" SHOWSERVERCONFIGRELEASE",因此您可以输入服务器的名称.如果您对公司使用此代码,则可以输入适当的值并使用常规的" RELEASE"版本.但是,它只会以任何一种方式询问您一次服务器名称,并将该值存储在注册表中.首次登录BugReporter时,可以使用" fp"," sp"或" tp"作为登录名.(If you run the demo, you will need to run the SQL script first in a database that you create on your SQL Server, with database, username, and passwords of ‘bugreporter’. The demo was built as ‘SHOWSERVERCONFIGRELEASE’ so that you are allowed to input the name of your server. If you use this code for your company, then you could put the appropriate values in and use the regular ‘RELEASE’ version. But it will only ask you for the server name once either way, and stores the value in the registry. The first time you log in to BugReporter, you can use ‘fp’,‘sp’, or ‘tp’ as login names.)
我已经在该应用程序中使用了ADO,(I’ve used ADO in this application by using the) #import
指示.该文件的路径在您的计算机上可能不同.(directive. The path to this file may be different on your computer.)
#import "C:\Program Files\Common Files\System\ado\msado15.dll" \
no_namespace \
rename("EOF", "adoEOF")
使用代码(Using the code)
运行应用程序后,转到"工具"菜单,然后选择"维护"或单击工具栏上的齿轮图标.您将需要设置一个项目以将所有错误放入应用程序中.添加新项目后,请确保添加版本号!由于维护工作可能要由程序员来完成,因此我没有在该屏幕中包含很多功能.但是,如果项目或用户已经与错误绑定,则不应删除它们.另外,由于此应用程序是在我们的局域网上使用的,因此我使用"计算机名"字段来跟踪用户的计算机名,以发送警报和聊天.(Once you have the application running, go to the ‘Tools’ menu, and select ‘Maintenance’ or click the gear icon on the toolbar. You will need to set up a project to put any bugs into the application. Once you add a new project, be sure to add a version number! Since the maintenance is probably going to be done by the programmers, I haven’t included a lot of functionality to this screen. However, it should not allow you to delete a project or user if they’re tied to a bug already. Also, since this app is used on our LAN, I use the ‘computername’ field to keep track of the users' computer name for sending alerts and chatting.)
要添加新的错误报告,请单击"新建".这会将用户置于"(To add a new bug report, click on ‘New’. This puts the user in ‘) NEW
的状态. ("(’ state. (The ‘) state
' 是一个(’ is an) enum
该属性用于启用/禁用控件,并确定如何保存错误(如果该错误位于"(property used for enabling/disabling of controls, and to determine how to save a bug if it is in ‘) EDIT
' 要么 ‘(’ or ‘) NEW
‘模式.)需要某种类型的描述,以及"提交者",“提交给"和"版本”.(’ mode.) Some type of description is required, as well as the ‘Submitted By’, ‘Submitted To’, and ‘Version’.)
要更新错误(通常由提交错误的人首先完成),请点击"编辑"按钮.这使您处于"(To update a bug, (usually done by the person who submitted the bug in the first place), click the ‘Edit’ button. This puts you in ‘) EDIT
‘模式.现在,您可以更改错误提交的任何参数.(’ mode. You can now change any of the parameters of the bug submittal.)
当程序员希望对错误做出响应时,请按" Respond".这将启用"返回状态注释"编辑框和"返回状态"组合.(When a programmer wishes to respond to a bug, press ‘Respond’. This will enable the ‘Return Status Notes’ edit box, and the ‘Return Status’ combo.)
如果选择了错误,则可以通过以下方式添加附件:在任何模式下将项目拖动到应用程序上,或单击"附件"列表框中旁边的"加号"图标(If there’s a bug selected, you can add an attachment by dragging an item onto the application in any mode, or clicking the ‘Plus’ icon next to the attachments listbox in ‘) NEW
' 要么 ‘(’ or ‘) EDIT
‘模式.执行此操作时,文件的实际字节以及文件名和扩展名将被保存在数据库中.要查看附件,请在列表框中双击它.该文件是从数据库中重新创建的,并保存在名为"(’ mode. When you do this, the actual bytes of the file are saved in the database, along with the filename and extension. To view an attachment, double-click on it in the listbox. The file is re-created from the database and saved in a folder called ‘)温度(temp)‘在BugReporter所在的文件夹中.然后我用(’ in the same folder where BugReporter is located. I then use) ShellExecute()
使用默认应用程序打开文件.这些文件被标记为只读,因此,如果您打开它,然后又忘记了它是从BugReporter打开的,则不允许您将副本保存在"(to open the file with the default application. The files are marked as Read-Only so that if you open it and then forget it was opened from BugReporter, it won’t allow you to save over the copy in the ‘)温度(Temp)‘文件夹.退出BugReporter后,此文件夹将被清除,因此请确保不要在该文件夹中保存其他任何内容!您可以通过单击列表框旁边的"减号"从错误中删除附件.该代码如下所示:(’ folder. This folder is cleaned out upon exiting BugReporter, so make sure you don’t save anything else in this folder!! You can remove attachments from a bug by clicking the ‘Minus’ sign next to the listbox. Here’s what that code looks like:)
void CBugReporterView::OnLbnDblclkScaps()
{
CString url = _T("");
int index = m_lstScaps.GetCurSel();
m_lstScaps.GetText(index, url);
int data = (int)m_lstScaps.GetItemData(index);
CString strMessage,strWhere,strDirectory;
char szPath[512];
BYTE* pBuf;
BYTE* pBytes;
_variant_t varBLOB;
unsigned long nLength;
try
{
BeginWaitCursor();
_RecordsetPtr rst;
strWhere.Format("LinkID = %d",data);
rst = theApp.GetRecordset(_T("*"),_T("tblLink") ,strWhere);
CString str,strPath;
FieldsPtr pFields = rst->GetFields();
FieldPtr pField,pName;
pField= pFields->GetItem(_T("FileBytes"));
pName = pFields->GetItem(_T("Link"));
nLength = pField->GetActualSize();
str.Format("%s",(char*)_bstr_t(pName->Value));
varBLOB = pField->GetChunk(nLength);
//pBuf = new BYTE[nLength];
SafeArrayAccessData(varBLOB.parray,(void **)&pBuf);
// Initialize the data member variable with the data.
pBytes = pBuf;
// Unlock the safe array data.
SafeArrayUnaccessData(varBLOB.parray);
::GetModuleFileName(NULL,szPath,512);
strPath.Format("%s",szPath);
int pos = strPath.ReverseFind('\\');
strDirectory = strPath.Left(pos + 1) + "temp\\";
strPath = strDirectory + url;
CreateDirectory(strDirectory,NULL);
CFile file;
CFileException ex;
CFileStatus status;
status.m_attribute = 0;
//if file already exists in this directory,
//remove read-only attribute, then delete it
if(file.Open(strPath,CFile::modeRead,&ex))
{
file.Close();
CFile::SetStatus(strPath,status);
DeleteFile(strPath);
}
//if we're able to create the file
if(file.Open(strPath,CFile::modeCreate | CFile::modeWrite,&ex))
{
file.Write(pBytes,nLength);
file.Close();
file.GetStatus(status);
status.m_attribute |= 0x01; //read only
CFile::SetStatus(strPath,status);
int iReturn = (int) ShellExecute(NULL, _T("open"),
strPath, NULL, NULL, SW_SHOWNORMAL);
// If ShellExecute returns an error code, let the user know.
if (iReturn <= 32)
MessageBox (_T("Cannot open file. File may have"
" been moved or deleted."), _T("Error!"),
MB_OK | MB_ICONEXCLAMATION) ;
if(url.GetLength()==0)
MessageBox (_T("This is an empty entry!"
" Try clicking a filled link! "),
_T("Error!"), MB_OK | MB_ICONEXCLAMATION) ;
}//if(file.Open(strPath,CFile::modeCreate | CFile::modeWrite,&ex))
else //file might have been opened already
{
AfxMessageBox("File could not be opened from this location.\r\n"
"Check to make sure you don\'t already"
" have this attachment open.",MB_ICONINFORMATION);
}
}
MYCATCHALL
VariantClear(&varBLOB);
url.ReleaseBuffer();
EndWaitCursor();
}
将错误标记为返回状态的"已修复"或"不可复制"后,将其视为"准备测试",您可以通过使用应用程序右上方的组合框更改当前视图来查看该视图,该组合框位于"准备就绪"下.测试’.如果该错误的提交者重新测试该错误并发现该错误已解决,则他们应将其标记为错误.如果不是,用户可以在描述中添加更多文本并保存.保存时,它将询问您是否要将错误标记为"返回程序员".如果是这样,该错误将以黄色突出显示其"类型"列,以使其对程序员更加突出.(After a bug has been marked as ‘fixed’ or ‘irreproducible’ for return status, it is deemed ‘Ready to Test’, which you can see by changing the current view with the combobox on the upper right of the application under ‘Ready to Test’. If the submitter of the bug re-tests the bug and sees that it is resolved, they should mark it as such. If not, the user can add more text to the description and save. When saving, it will ask if you want to mark the bug as ‘Return to Programmer’. If so, the bug will show up with its ‘type’ column highlighted in yellow so that it stands out to the programmer.)
数据库中表" tlkptype"中的所有类型都填充了"当前视图"组合.我在SQL脚本中包括一些默认类型以填充此表,还为"返回状态"提供了一些默认类型. (我认为这可能已经太多了,因此您可能不必再添加了.)组合框中还添加了硬编码的值,例如" Ready To Test"," Mine"和具有itemdata在组合框中与它们相关联,以在(The ‘Current View’ combo is populated from all the types in the table ‘tlkptype’ in the database. I have included some default types in the SQL script to populate this table, as well as some for the ‘Return Status’. (I think this is probably already too many, so you probably won’t have to add anymore.) There are also hard-coded values that are added to the combobox, like ‘Ready To Test’, ‘Mine’, and have itemdata associated with them in the combobox to generate the appropriate SQL statement in the) Refresh()
程序.这些是添加到"当前视图"组合框中的其他类型,以及从它们生成的SQL:(procedure. These are the other types added to ‘Current View’ combobox, and the SQL generated from them:)
switch(nFilter)
{
case 1000:
//only the current user's bugs
strWhere2.Format(_T(" AND dbo.tblBug."
"SubmittedToID = %d"),theApp.m_nUserID );
break;
case 1001:
//only unresolved bugs
strWhere2 = _T(" AND dbo.tblBug.Resolved = 0");
break;
case 1002:
//only unanswered bugs
strWhere2 = _T(" AND dbo.tblBug.ReturnStatusID = 4");
break;
case 1003:
strWhere2 = _T(" AND dbo.tblBug.Resolved = 1");
break;
case 1004:
//all
strWhere2 = _T("");
break;
case 1005:
//ready to test
strWhere2 = _T(" AND ((dbo.tblBug.Resolved = 0 AND
dbo.tblBug.ReturnStatusID = 2) OR
(dbo.tblBug.Resolved = 0 AND
dbo.tblBug.ReturnStatusID = 1))");
break;
case 1006:
//returned to programmer
strWhere2 = _T(" AND dbo.tblBug.RTP = 1");
break;
default:
//otherwise, it's just a bug type id
strWhere2.Format(_T(" AND dbo.tblBug.TypeID = %d"),nFilter);
}
保存/编辑/响应错误后,您还将看到一个对话框(除非您已通过"选项"屏幕将其关闭),询问您是否要向适当的人发送警报.这将显示一个简短的消息框,告诉您警报是否成功发送.您也可以随时在"提交者"或"提交给"组合框中单击用户名旁边的按钮,向用户发送警报.您不能向自己,“未知"或任何将"计算机"设置为计算机名的用户发送警报.收到警报时,您将收到一个消息框,然后单击"确定”,然后将您设置为适当的错误.(After saving/editing/responding to a bug, you will also get a dialog (unless you have turned it off through the ‘Options’ screen) asking if you would like to send the appropriate person an alert. This will display a brief message box that will tell you if your alert was sent successfully or not. You may also send a user an alert at any time by clicking the button next to their name in ‘Submitted By’ or ‘Submitted To’ comboboxes. You cannot send an alert to yourself, or to ‘UNKNOWN’, or to any user with ‘COMPUTER’ set as their computername. When you receive an alert, you will receive a messagebox, and after clicking ‘OK’, you will be set to the appropriate bug.)
您可以在此处配置几个选项,我认为其中大多数是不言自明的.只需确保更改任何选项后单击"应用",否则它们将不会保存.(There are several options you can configure here, and I think most of them are self-explanatory. Just make sure that you click ‘Apply’ after changing any options or they won’t be saved.)
当然,此屏幕将填充系统中除您之外的所有用户.只需选择您要与之聊天的用户,然后向他们发送消息即可.如果用户未运行BugReporter或将自己置于"请勿打扰"模式(在"工具"菜单上找到并带有复选标记,则该信息将不会通过).发送的每条消息都会打开和关闭聊天套接字,因此您可以一次与多个人聊天.如果您正在与Person1聊天并收到来自Person2的消息,则它将Person2放入SendTo组合中,以便您的下一个消息发送到Person2,除非您正在输入中间.在这种情况下,它不会切换此人,因为我假设如果您已经在键入,那么您希望当前消息发送给您已经选择的人.我实施了一种自制的加密算法,可将您的文本隐藏在嗅探器中.它不是计算机科学的赢家,这只是我想尝试的东西. :)(This screen populates all the users in your system except you, of course. Just select which user you want to chat with, and send them a message. Your message won’t go through if the user doesn’t have BugReporter running or if they have put themselves in ‘Do not Disturb’ mode (found on the ‘Tools’ menu and indicated by a checkmark). Every message sent opens and closes the chat socket, so you can chat with multiple people at once. If you’re chatting with Person1 and receives a message from Person2, it puts Person2 in the SendTo combo so that your next messge goes to Person2, unless you’re in the middle of typing. In that case, it won’t switch the person, because I’d assumed that if you were already typing, then you want your current message to go to the person you’ve already selected. I implemented a homemade encryption algorithm to hide your text from sniffers. It’s no Computer Science winner, it was just something I wanted to try. :))
克里斯`桑德(Chris Maunder)(Chris Maunder’s) MFC网格(MFC Grid) 已经在使用或不使用Doc/View架构的情况下完成了打印工作,但是我增加了一次打印单个bug的方法,以便您可以看到整个"说明",“响应"以及所有附件(文件名是列在"附件:“下).如果您当前的视图是"准备测试”,它将提示您输入"版本号”.这不是必需的,这只是在报告上显示文本值以供测试人员参考的一种方法.(already takes care of the printing with or without the Doc/View architecture, but I added a way to print a single bug at a time so that you can see the entire ‘Description’, ‘Response’, and any attachments (the filenames are listed under ‘Attachments:'). If your current view is ‘Ready to Test’, it will prompt you for a ‘Version Number’. This is not necessary, it’s just a way to display a text value on the report for the tester’s reference.)
“查找"对话框允许您输入不同的条件以查找先前提交的错误.拥有列表后,您也可以打印列表.可能没有那么大的帮助,但是它是免费的,因为我要做的就是调用网格的(The ‘Find’ Dialog allows you to put in different criteria to find previously submitted bugs. You can also print the list once you have one. It might not be that helpful, but it’s free, since all I had to do was call the grid’s) Print()
功能!找到错误后,您可以双击它以在主屏幕上查看它.该对话框是无模式的,因此您可以根据需要来回切换.(function! After you locate a bug, you can double-click it to view it on the main screen. This dialog is modeless, so you can switch back and forth as necessary.)
兴趣点(Points of Interest)
同样,使用MFC Grid的内置功能,我允许用户将当前列表另存为逗号分隔的文本文件,以防用户要将其导出到其他地方.我使用了一个非常通用的错误处理程序,以HTML格式写出错误.我将其定义为(Again, using the MFC Grid’s built-in functionality, I’ve allowed the user to save the current list as a comma-delimited text file, in case they want to export it to somewhere else. I’ve used a pretty generic error handler that writes out the errors in HTML format. I’ve defined this as) MYCATCHALL
在里面(in the)*stdafx.h(stdafx.h)*文件:(file:)
#define MYCATCHALL catch(CException* e) \
{ \
m_pErrorHandler->HandleError(e,__FUNCTION__); \
} \
catch(_com_error e) \
{ \
m_pErrorHandler->HandleError(e,__FUNCTION__); \
} \
catch(...) \
{\
m_pErrorHandler->HandleError(__FUNCTION__);\
}
大多数对话框都有动画(您可以在"选项"对话框中将其关闭).我为应用程序类创建了一个函数来处理此问题.只需发送(Most of the dialogs have animation (which you can turn off in the ‘Options’ dialog). I made a function for the application class to handle this. Just send it the) HWND
要设置动画的对话框,它会随机选择一个.我删除了淡入/淡出动画,因为控件无法正确绘制.(of the dialog you want to animate, and it randomly picks one. I removed the Fade In/Out animation because controls weren’t painting correctly.)
void CBugReporterApp::AnimateDialog(HWND hWnd)
{
DWORD dwTemp2,dwTemp,dwAnimate = AW_ACTIVATE;
int nFirst,nSecond;
try
{
//seed randomNumber Generator
srand( (unsigned)time( NULL ) );
nFirst = rand() % 3 + 1;
switch(nFirst)
{
case 1: dwTemp = AW_SLIDE; break;
case 2:
//removed because it was AW_BLEND which
//doesn't seem to repaint controls correctly
case 3: dwTemp = AW_CENTER; break;
}
dwAnimate |= dwTemp;
//these next values will only work with AW_SLIDE
if(nFirst == 1)
{
srand( (unsigned)time( NULL ) );
nSecond = rand() % 4 + 1;
switch(nSecond)
{
case 1: dwTemp2 = AW_HOR_POSITIVE; break;
case 2: dwTemp2 = AW_HOR_NEGATIVE; break;
case 3: dwTemp2 = AW_VER_POSITIVE; break;
default:dwTemp2 = AW_VER_NEGATIVE;
}
dwAnimate |= dwTemp2;
srand( (unsigned)time( NULL ) );
nSecond = rand() % 2;
if(dwTemp2 == AW_VER_POSITIVE || dwTemp2 == AW_VER_NEGATIVE)
{
dwTemp2 = 0;
switch(nSecond)
{
case 1: dwTemp2 = AW_HOR_POSITIVE; break;
case 2: dwTemp2 = AW_HOR_NEGATIVE; break;
}
dwAnimate |= dwTemp2;
}//if(dwTemp2 == AW_VER_POSITIVE || dwTemp2 == AW_VER_NEGATIVE)
else
{
dwTemp2 = 0;
switch(nSecond)
{
case 1: dwTemp2 = AW_VER_POSITIVE; break;
case 2: dwTemp2 = AW_VER_NEGATIVE; break;
}
dwAnimate |= dwTemp2;
}
}//if(nFirst == 1)
::AnimateWindow(hWnd,200,dwAnimate);
}
MYCATCHALL
}
我还使用了一些辅助功能来处理记录集和组合框.(There are also a few helper functions that I use for dealing with recordsets and comboboxes.)
void CBugReporterApp::CloseRecordset(_RecordsetPtr rst)
int CBugReporterApp::GetIntField(CString strSQL)
void CBugReporterApp::FillCombo(CString strTable, CString strDataField,
CString strDisplayField, CComboBox& cbo,
CString strAlias,BOOL bAddEmpty)
CString CBugReporterApp::GetStringField(CString strField,
CString strTable, CString strWhere)
void CBugReporterApp::ExecuteSQL(CString strSQL)
void CBugReporterApp::SetComboFromID(CComboBox& cbo, int nID)
void CBugReporterApp::EmptyCombo(CComboBox& cbo)
_RecordsetPtr CBugReporterApp::GetRecordset(CString strFields,
CString strTable, CString strWhere)
“缩放"对话框,主应用程序窗口以及大多数其他应用程序都有一个值,该值将保存在注册表中以用于放置,以便其位置和大小保持不变.我从在某处找到的示例中获取了此信息.这是"聊天"对话框的外观:(The ‘Zoom’ dialog, the main app window, and most others have a value that will be saved in the registry for their placement so that their positions and sizes are persistent. I took this from an example I found somewhere. This is what it looks like for the Chat dialog:)
void CChatDlg::OnDestroy()
{
CDialog::OnDestroy();
WINDOWPLACEMENT wp;
GetWindowPlacement(&wp);
theApp.WriteProfileBinary("Settings", "ChatWindowPos",
(LPBYTE)&wp,sizeof(wp));
}
我用更好的图标使工具栏按钮变大了.(I made the toolbar buttons bigger with (I think) better icons.)
//create an HBITMAP for the image
HBITMAP hbm = (HBITMAP)::LoadImage(AfxGetInstanceHandle(),
MAKEINTRESOURCE(IDB_BITMAP1), IMAGE_BITMAP, 0,0, // cx, cy
LR_CREATEDIBSECTION | LR_LOADMAP3DCOLORS );
//make a CBitmap and attach HBITMAP to it
CBitmap bm;
bm.Attach(hbm);
//create imagelist and specify 256 colors
int ret = m_ilToolBar.Create(32,32,ILC_COLOR8 | ILC_MASK,1,0);
ret = m_ilToolBar.Add(&bm,RGB(0,0,0));
//The second parameter sets the gray background color to transparent
m_wndToolBar.GetToolBarCtrl().SetImageList(&m_ilToolBar);
//make toolbar buttons the appropriate size
SIZE szButton,szImage;
szButton.cx = 39; //button width must be 7 pixels greater than image
szButton.cy = 38; //height must be 6 pixels greater than image
szImage.cx = 32;
szImage.cy = 32;
m_wndToolBar.SetSizes(szButton,szImage);
//should be called after any resizing is done to buttons or images
m_wndToolBar.GetToolBarCtrl().AutoSize();
当您在主窗口中的网格上单击鼠标右键时,我还添加了一个弹出菜单.您可以删除选定的错误,也可以更改选定的错误的项目.打开弹出菜单后,项目的辅助菜单将显示当前项目以外的所有项目.每次您查看菜单时,此操作都会动态完成,并在我为主窗口创建的子类网格控件(称为(I also added a popup menu for when you right-click on the grid in the main window. You can either delete the selected bug(s), or change the project for the selected bug(s). Once you open the popup menu, the secondary menu for the projects shows all the projects except the current one. This is done dynamically every time you view the menu and is implemented in the subclassed grid control I made for the main window, called) CMyGridCtrl
:(:)
void CMyGridCtrl::OnRButtonUp(UINT nFlags, CPoint point)
{
if(this->GetRowCount() > 1)
{
_RecordsetPtr rst;
CString strSQL;
CPoint mypoint(point);
ClientToScreen(&mypoint);
//convert to screen coordinates to get point to display popupmenu
CMenu* pMenu = this->pPopupMenu->GetSubMenu(0);
CMenu* pMenu2 = pMenu->GetSubMenu(0);
//remove all items from the 'Projects' submenu
while(pMenu2->RemoveMenu(0,MF_BYPOSITION));
strSQL.Format(_T("SELECT ProjectID,Project FROM tblProject"
" WHERE ProjectID <> %d"),this->m_pView->m_nCurrentProjectID);
VARIANT* var = NULL;
rst.CreateInstance(__uuidof (Recordset));
rst->CursorLocation = adUseClient;
rst = theApp.g_Cnn->Execute(strSQL.AllocSysString(),var,0L);
FieldsPtr pFields;
FieldPtr pID,pName;
if(!rst->adoEOF)
pFields = rst->Fields;
int nStatusID = 0;
CString strStatus;
//loop through and get all the projects except
//the current one, then add them to submenu
while(!(rst->adoEOF))
{
pID = pFields->GetItem(_T("ProjectID"));
pName = pFields->GetItem(_T("Project"));
nStatusID = (int)pID->Value;
strStatus.Format("%s",(char*)_bstr_t(pName->Value));
pMenu2->AppendMenu(MF_STRING,nStatusID,strStatus);
rst->MoveNext();
}
pMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON,
mypoint.x,mypoint.y,this);
theApp.CloseRecordset(rst);
}
CGridCtrl::OnRButtonUp(nFlags, point);
}
放大镜按钮将您放大,因此在查看/编辑错误时,您将有更多的查看空间.最后一个项目(错误,视图)都保存在注册表中,以便应用程序将您带回到重新启动应用程序时的位置. " BUGID"出现在网格中,以便在打印列表时,如果描述太短,则可以通过其编号轻松识别错误.(The magnifying glass buttons zoom you in so you you have more viewing space when viewing/editing bugs. The last project, bug, view are all saved in the registry so that the application puts you right back where you were when starting the app again. ‘BUGID’ shows up in the grid so that when printing out a list, you can easily identify a bug by its number if the description is too short.)
已知问题(Known Problems)
- 如果应用程序通宵开放,它有时会失去连接,必须重新启动.(If app is open overnight, it sometimes loses connection and has to be restarted.)
- 应该使用(Should use)
CString
发送聊天消息时的变量.(variable when sending chat messages.) - 我的MFC Grid Control副本仍然存在错误(My copy of the MFC Grid Control still had a bug in the)
EnsureVisible()
功能,请参阅我实施的修复程序(function, see the fix I implemented) 这里(here) .如果您自己编译时此错误仍在源中,则在调用时它将崩溃(. If this bug is still in the source when you compile it yourself, it will crash when calling)EnsureVisible()
在BugReporter的(in BugReporter’s)Refresh()
如果网格没有焦点则起作用.(function if the grid doesn’t have focus.)
闭幕(Closing)
我希望这个应用程序能对任何人有所帮助,并真的希望您给它评分.我敢肯定,可能还没有发现其他错误,但是我很高兴知道这些错误,并将相应地更改代码.无论您是否喜欢该文章,请对其进行评分.如果您不喜欢它,并给该文章给予较低的评分,我希望您也能发表评论,以便我知道原因.(I hope this app helps anybody and really hope you rate it. I’m pretty sure there are probably other bugs that I haven’t found yet, but I’d be happy to know about them and will change the code accordingly. Whether you like the article or not, please rate it. If you don’t like it and give the article a low rating, I hope that you’ll also leave a comment so that I know why.)
随意以您喜欢的任何方式使用此代码.欢迎进行任何添加和/或更改.(Feel free to use this code in any way you like. Any additions and/or changes are welcome.)
历史(History)
- 4.2版-2005年1月26日发布.(Version 4.2 - Posted 01/26/2005.)
许可
本文以及所有相关的源代码和文件均已获得The Code Project Open License (CPOL)的许可。
C++ VC7.1 WinXP Windows Win2K Visual-Studio MFC VS.NET2003 Dev 新闻 翻译