803 lines
38 KiB
C++
803 lines
38 KiB
C++
#include "StdAfx.h"
|
|
#include "resource.h"
|
|
#include "EarThwormDef.h"
|
|
#include "askaiPaletteSet.h"
|
|
#include "AIChatSettingDlg.h"
|
|
#include "AICloudSettingDlg.h"
|
|
#include <atlconv.h>
|
|
|
|
namespace
|
|
{
|
|
// 请求
|
|
SHAI::Request g_Request;
|
|
|
|
// 回答
|
|
SHAI::Response g_Response;
|
|
|
|
// 线程句柄
|
|
HANDLE g_hThread = NULL;
|
|
|
|
unsigned int __stdcall requestSendProc(void *pParam)
|
|
{
|
|
g_Request.send(g_Response);
|
|
|
|
CString finishReason(AIJSON::utf2w(g_Response.finish_reason()).c_str());
|
|
if (finishReason.CompareNoCase(_T("stop")) == 0)
|
|
{
|
|
if (g_Response.needRecordContext() && !g_Response.allContent().empty())
|
|
g_Request.addAssistantMessage(g_Response.allContent().c_str());
|
|
}
|
|
else
|
|
{
|
|
if (finishReason.CompareNoCase(_T("length")) == 0)
|
|
{
|
|
g_aiPaletteSet::instance().sendTextToAnswer(_T("\r\n达到生成的最大长度限制。"));
|
|
}
|
|
else if (finishReason.CompareNoCase(_T("content_filter")) == 0)
|
|
{
|
|
g_aiPaletteSet::instance().sendTextToAnswer(_T("\r\n内容因安全策略被过滤系统拦截,可能是触发了敏感词、违规内容检测等。"));
|
|
}
|
|
else if (finishReason.CompareNoCase(_T("timeout")) == 0)
|
|
{
|
|
g_aiPaletteSet::instance().sendTextToAnswer(_T("\r\n超时。"));
|
|
}
|
|
else if (finishReason.CompareNoCase(_T("insufficient_system_resource")) == 0)
|
|
{
|
|
g_aiPaletteSet::instance().sendTextToAnswer(_T("\r\n由于后端推理资源受限,请求被打断。"));
|
|
}
|
|
else
|
|
{
|
|
#ifdef NDEBUG
|
|
g_aiPaletteSet::instance().sendTextToAnswer(_T("\r\n服务器繁忙,请稍候再试。"));
|
|
#else
|
|
g_aiPaletteSet::instance().sendTextToAnswer(
|
|
CString(_T("\r\n")) + finishReason);
|
|
#endif
|
|
}
|
|
|
|
// 弹出最后一条 user message
|
|
g_Request.popbackMessage();
|
|
|
|
return 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
#pragma region CAskAIPaletteSet
|
|
|
|
IMPLEMENT_DYNAMIC(CAskAIPaletteSet, CAdUiPaletteSet)
|
|
BEGIN_MESSAGE_MAP(CAskAIPaletteSet, CAdUiPaletteSet)
|
|
ON_WM_CREATE()
|
|
ON_WM_DESTROY()
|
|
END_MESSAGE_MAP()
|
|
|
|
CAskAIPaletteSet::CAskAIPaletteSet()
|
|
: m_pAiPalette(NULL)
|
|
{
|
|
}
|
|
|
|
CAskAIPaletteSet::~CAskAIPaletteSet()
|
|
{
|
|
}
|
|
|
|
bool CAskAIPaletteSet::CreatePaletteSet(LPCTSTR pszTitle)
|
|
{
|
|
CMDIFrameWnd* pFrame = acedGetAcadFrame();
|
|
ASSERT(NULL != pFrame);
|
|
|
|
if (!Create(pszTitle, WS_CHILD | WS_VISIBLE | CBRS_SIZE_DYNAMIC | CBRS_RIGHT, CRect(0, 0, 160, 100), pFrame))
|
|
{
|
|
acutPrintf(_T("\n创建失败!"));
|
|
return FALSE;
|
|
}
|
|
|
|
EnableDocking(CBRS_ALIGN_ANY);
|
|
RestoreControlBar(AFX_IDW_DOCKBAR_FLOAT);
|
|
|
|
m_pAiPalette = new CAskAIPalette;
|
|
if (m_pAiPalette->Create(WS_CHILD | WS_VISIBLE, _T("问问AI"), this, NULL))
|
|
AddPalette(m_pAiPalette);
|
|
|
|
if (this->GetPaletteCount() > 0)
|
|
{
|
|
SetActivePalette(0);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
int CAskAIPaletteSet::OnCreate(LPCREATESTRUCT lpCreateStruct)
|
|
{
|
|
if (CAdUiPaletteSet::OnCreate(lpCreateStruct) == -1)
|
|
return -1;
|
|
|
|
CWnd* pWnd = GetDlgItem(idCloseBtn);
|
|
ASSERT(NULL != pWnd);
|
|
pWnd->EnableWindow(FALSE);
|
|
|
|
static GUID cMenuBar = { 0x40929771, 0xf51d, 0x42ad, { 0x97, 0xa, 0x9a, 0xf9, 0xd3, 0x78, 0x2c, 0xea } };
|
|
|
|
|
|
SetToolID(&cMenuBar);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void CAskAIPaletteSet::OnDestroy()
|
|
{
|
|
CAdUiPalette* pPage = NULL;
|
|
while (GetPaletteCount() > 0)
|
|
{
|
|
pPage = GetPalette(0);
|
|
RemovePalette(pPage);
|
|
delete pPage;
|
|
}
|
|
CAdUiPaletteSet::OnDestroy();
|
|
}
|
|
|
|
BOOL CAskAIPaletteSet::PreTranslateMessage(MSG *pMsg)
|
|
{
|
|
if (pMsg->message == WM_KEYDOWN)
|
|
{
|
|
CWnd *pWnd = CWnd::FromHandle(pMsg->hwnd);
|
|
if (pWnd->GetDlgCtrlID() == IDC_EDIT_ASK
|
|
|| pWnd->GetDlgCtrlID() == IDC_EDIT_ANSWER )
|
|
{
|
|
if (pMsg->wParam == VK_ESCAPE)
|
|
return TRUE;
|
|
}
|
|
}
|
|
return CAdUiPaletteSet::PreTranslateMessage(pMsg);
|
|
}
|
|
|
|
bool CAskAIPaletteSet::OnClosing()
|
|
{
|
|
return (IDYES != MessageBox(_T("窗口即将关闭。\n\n是否要关闭?"), _T("问问AI"), MB_YESNO | MB_ICONQUESTION));
|
|
}
|
|
|
|
void CAskAIPaletteSet::GetFloatingMinSize(long * plMinWidth, long * plMinHeight)
|
|
{
|
|
*plMinWidth = 1024;
|
|
*plMinHeight = 800;
|
|
}
|
|
|
|
void CAskAIPaletteSet::SizeChanged(CRect * lpRect, BOOL bFloating, int flags)
|
|
{
|
|
CAdUiPaletteSet::SizeChanged(lpRect, bFloating, flags);
|
|
|
|
CRect rc(lpRect);
|
|
rc.DeflateRect(6, 6);
|
|
|
|
CString sKey;
|
|
CAdUiPalette* pPage = NULL;
|
|
for (int i = 0; i < GetPaletteCount(); i++)
|
|
{
|
|
pPage = GetPalette(i);
|
|
if (pPage != NULL)
|
|
{
|
|
((CAskAIPalette*)pPage)->MoveWindow(rc);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CAskAIPaletteSet::GetMinimumSize(CSize & size)
|
|
{
|
|
size.cx = 1024;
|
|
size.cy = 800;
|
|
CAdUiPaletteSet::GetMinimumSize(size);
|
|
}
|
|
|
|
void CAskAIPaletteSet::GetMaximumSize(CSize & size)
|
|
{
|
|
CAdUiPaletteSet::GetMaximumSize (size) ;
|
|
}
|
|
|
|
void CAskAIPaletteSet::sendTextToAnswer(LPCTSTR lpszText)
|
|
{
|
|
CString s(lpszText);
|
|
s.Replace(_T("\r\n"), _T("\n"));
|
|
s.Replace(_T("\n"), _T("\r\n"));
|
|
if (m_pAiPalette)
|
|
m_pAiPalette->sendTextToAnswer(s);
|
|
}
|
|
|
|
void CAskAIPaletteSet::setFocusToAsk()
|
|
{
|
|
if (m_pAiPalette)
|
|
m_pAiPalette->setFocusToAsk();
|
|
}
|
|
|
|
void CAskAIPaletteSet::refreshAiCloud()
|
|
{
|
|
if (m_pAiPalette && ::IsWindow(g_aiPaletteSet::instance().m_hWnd))
|
|
m_pAiPalette->refreshAiCloud();
|
|
}
|
|
|
|
void CAskAIPaletteSet::start()
|
|
{
|
|
#if ARX > 18
|
|
if (!::IsWindow(g_aiPaletteSet::instance().m_hWnd))
|
|
{
|
|
g_aiPaletteSet::instance().CreatePaletteSet(_T("问问AI"));
|
|
}
|
|
|
|
if (::IsWindow(g_aiPaletteSet::instance().m_hWnd))
|
|
{
|
|
g_aiPaletteSet::instance().m_pDockSite->ShowControlBar(&g_aiPaletteSet::instance(), TRUE, FALSE);
|
|
g_aiPaletteSet::instance().setFocusToAsk();
|
|
g_aiPaletteSet::instance().refreshAiCloud();
|
|
}
|
|
#else
|
|
AfxMessageBox(_T("CAD2013以下版本不支持此功能。"));
|
|
#endif
|
|
}
|
|
void CAskAIPaletteSet::setAiCloud()
|
|
{
|
|
#if ARX > 18
|
|
CAcModuleResourceOverride myResources;
|
|
CAICloudSettingDlg dlg;
|
|
dlg.DoModal();
|
|
#else
|
|
AfxMessageBox(_T("CAD2013以下版本不支持此功能。"));
|
|
#endif
|
|
}
|
|
#pragma endregion
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#pragma region CAskAIPalette
|
|
IMPLEMENT_DYNAMIC(CAskAIPalette, CAdUiPalette)
|
|
BEGIN_MESSAGE_MAP(CAskAIPalette, CAdUiPalette)
|
|
ON_WM_CREATE()
|
|
ON_WM_PAINT()
|
|
ON_WM_WINDOWPOSCHANGED()
|
|
ON_BN_CLICKED(IDC_BTN_NEWCHAT, &CAskAIPalette::OnBtnClickNewChat)
|
|
ON_BN_CLICKED(IDC_BTN_UPLOAD, &CAskAIPalette::OnBtnClickUpload)
|
|
ON_BN_CLICKED(IDC_BTN_EN2CH, &CAskAIPalette::OnBtnClickTranslate)
|
|
ON_BN_CLICKED(IDC_BTN_EXPORT, &CAskAIPalette::OnBtnClickExport)
|
|
ON_BN_CLICKED(IDC_BTN_SETTING, &CAskAIPalette::OnBtnClickSetting)
|
|
ON_BN_CLICKED(IDC_BTN_SEND, &CAskAIPalette::OnBtnClickSend)
|
|
ON_CBN_SELCHANGE(IDC_COMBO_MODEL, &CAskAIPalette::OnComboBoxModelListSelChange)
|
|
ON_CBN_DROPDOWN(IDC_COMBO_MODEL, &CAskAIPalette::OnComboBoxModelListDropDown)
|
|
END_MESSAGE_MAP()
|
|
|
|
CAskAIPalette::CAskAIPalette()
|
|
: m_pEdAnswer(NULL)
|
|
, m_pEdAsk(NULL)
|
|
, m_pBtnNewChat(NULL)
|
|
, m_pBtnUploadFile(NULL)
|
|
, m_pBtnTranslate(NULL)
|
|
, m_pBtnSend(NULL)
|
|
, m_pBtnExport(NULL)
|
|
, m_pBtnSetting(NULL)
|
|
, m_pStaticCloudName(NULL)
|
|
, m_pComboModelList(NULL)
|
|
, m_pAiCloud(NULL)
|
|
{
|
|
|
|
LOGFONT lf;
|
|
::GetObject((HFONT)GetStockObject(DEFAULT_GUI_FONT), sizeof(lf), &lf);
|
|
CClientDC dc(this);
|
|
_tcscpy(lf.lfFaceName, _T("微软雅黑"));
|
|
lf.lfHeight = -MulDiv(13, GetDeviceCaps(dc.m_hDC, LOGPIXELSY), 72);
|
|
m_fontEdit.CreateFontIndirect(&lf);
|
|
|
|
::memset(&lf, 0, sizeof(LOGFONT));
|
|
::GetObject((HFONT)GetStockObject(DEFAULT_GUI_FONT), sizeof(lf), &lf);
|
|
_tcscpy(lf.lfFaceName, _T("宋体"));
|
|
lf.lfHeight = -MulDiv(12, GetDeviceCaps(dc.m_hDC, LOGPIXELSY), 72);
|
|
m_fontBTN.CreateFontIndirect(&lf);
|
|
}
|
|
|
|
CAskAIPalette::~CAskAIPalette()
|
|
{
|
|
DELETE_PTR(m_pEdAnswer);
|
|
DELETE_PTR(m_pEdAsk);
|
|
DELETE_PTR(m_pBtnNewChat);
|
|
DELETE_PTR(m_pBtnUploadFile);
|
|
DELETE_PTR(m_pBtnTranslate);
|
|
DELETE_PTR(m_pBtnSend);
|
|
DELETE_PTR(m_pBtnExport);
|
|
DELETE_PTR(m_pBtnSetting);
|
|
DELETE_PTR(m_pStaticCloudName);
|
|
DELETE_PTR(m_pComboModelList);
|
|
DELETE_PTR(m_pAiCloud);
|
|
::DeleteObject(m_fontEdit);
|
|
::DeleteObject(m_fontBTN);
|
|
}
|
|
|
|
void CAskAIPalette::sendTextToAnswer(LPCTSTR lpszText)
|
|
{
|
|
if (!::IsWindow(g_aiPaletteSet::instance().m_hWnd)) return;
|
|
|
|
int nLength = m_pEdAnswer->GetWindowTextLength();
|
|
m_pEdAnswer->SetSel(nLength, nLength);
|
|
|
|
m_pEdAnswer->ReplaceSel(lpszText);
|
|
m_pEdAnswer->LineScroll(m_pEdAnswer->GetLineCount());
|
|
}
|
|
|
|
void CAskAIPalette::setFocusToAsk()
|
|
{
|
|
m_pEdAsk->SetFocus();
|
|
}
|
|
|
|
void CAskAIPalette::refreshAiCloud()
|
|
{
|
|
DELETE_PTR(m_pAiCloud);
|
|
|
|
if (!CAICloudSettingDlg::getActiveAIClouds(m_pAiCloud))
|
|
{
|
|
AfxMessageBox(_T("未找到当前的AI配置,请先运行co_llm命令进行配置。"));
|
|
acedPostCommand(_T("co_llm "));
|
|
return;
|
|
}
|
|
|
|
CAIChatSettingDlg::getChatConfig(m_chatConfig);
|
|
|
|
m_pAiCloud->getModels();
|
|
if (m_pAiCloud->models().size() == 0)
|
|
{
|
|
AfxMessageBox(_T("获取模型列表失败,请重试,或者更换供应商。"));
|
|
return;
|
|
}
|
|
|
|
g_Request.setapikey(m_pAiCloud->apiKey().c_str());
|
|
g_Request.seturl(m_pAiCloud->endpoint().c_str());
|
|
g_Request.setmodel(m_pAiCloud->currentModel().c_str());
|
|
|
|
g_Request.set_temperature(m_chatConfig.temperature());
|
|
g_Request.set_top_p(m_chatConfig.top_p());
|
|
g_Request.set_top_k(m_chatConfig.top_k());
|
|
g_Request.set_max_tokens(m_chatConfig.max_tokens());
|
|
g_Request.set_frequency_penalty(m_chatConfig.frequency_penalty());
|
|
|
|
m_pComboModelList->ResetContent();
|
|
const std::vector<std::string> &models = m_pAiCloud->models();
|
|
int idx(-1);
|
|
for (size_t i(0); i < models.size(); ++i)
|
|
{
|
|
idx = m_pComboModelList->AddString(AIJSON::utf2w(models[i]).c_str());
|
|
if (m_pAiCloud->currentModel() == models[i])
|
|
m_pComboModelList->SetCurSel(idx);
|
|
}
|
|
m_pStaticCloudName->SetWindowText(AIJSON::utf2w(m_pAiCloud->cloudName()).c_str());
|
|
|
|
CalcCtrlPosition();
|
|
}
|
|
|
|
void CAskAIPalette::OnBtnClickNewChat()
|
|
{
|
|
g_Request.clearMessages();
|
|
g_Response.clear();
|
|
m_pEdAnswer->SetWindowText(_T(""));
|
|
}
|
|
|
|
void CAskAIPalette::OnBtnClickUpload()
|
|
{
|
|
|
|
}
|
|
|
|
void CAskAIPalette::OnBtnClickTranslate()
|
|
{
|
|
if (hasActiveRequest())
|
|
{
|
|
AfxMessageBox(_T("还有一个问题没有解答完成,请稍等!"));
|
|
return;
|
|
}
|
|
|
|
CString sAsk;
|
|
m_pEdAsk->GetWindowText(sAsk);
|
|
if (sAsk.IsEmpty())
|
|
{
|
|
AfxMessageBox(_T("消息为空!"));
|
|
return;
|
|
}
|
|
|
|
m_pEdAsk->SetWindowText(_T(""));
|
|
|
|
CString ss(m_pEdAnswer->GetLineCount() == 1 ? _T("") : _T("\r\n\r\n"));
|
|
sendTextToAnswer(ss + _T("原文:\r\n") + sAsk);
|
|
|
|
g_Request.clearMessages();
|
|
g_Request.setstream(true);
|
|
g_Response.clear();
|
|
|
|
// 不需要记录上下文
|
|
g_Response.setRecordContext(false);
|
|
|
|
g_Request.addSystemMessage(
|
|
"你是一个中英文翻译专家,将用户输入的中文翻译成英文,或将用户输入的英文翻译成中文。"
|
|
"对于非中文内容,它将提供中文翻译结果。"
|
|
"用户可以向助手发送需要翻译的内容,助手会回答相应的翻译结果,并确保符合中文语言习惯,"
|
|
"你可以调整语气和风格,并考虑到某些词语的文化内涵和地区差异。"
|
|
"同时作为翻译家,需将原文翻译成具有信达雅标准的译文。"
|
|
"\"信\" 即忠实于原文的内容与意图;"
|
|
"\"达\" 意味着译文应通顺易懂,表达清晰;"
|
|
"\"雅\" 则追求译文的文化审美和语言的优美。"
|
|
"目标是创作出既忠于原作精神,又符合目标语言文化和读者审美的翻译。");
|
|
|
|
g_Request.addUserMessage(CW2A((LPCTSTR)sAsk, CP_UTF8));
|
|
|
|
g_hThread = (HANDLE)::_beginthreadex(NULL
|
|
, 0
|
|
, requestSendProc
|
|
, NULL
|
|
, NULL
|
|
, NULL);
|
|
return;
|
|
}
|
|
|
|
void CAskAIPalette::OnBtnClickExport()
|
|
{
|
|
// 取出 Answer 的内容
|
|
CString sAnswer;
|
|
m_pEdAnswer->GetWindowText(sAnswer);
|
|
if (sAnswer.IsEmpty())
|
|
{
|
|
AfxMessageBox(_T("回答窗口内容为空!"));
|
|
return;
|
|
}
|
|
|
|
CTime currentTime = CTime::GetCurrentTime();
|
|
// 将时间格式化为 yyyy-mm-dd 字符串
|
|
CString dateString = currentTime.Format(_T("%Y-%m-%d"));
|
|
|
|
|
|
CString fileName;
|
|
fileName.Format(_T("上华AskAI%s.txt"), dateString);
|
|
|
|
CFileDialog dlg(FALSE
|
|
, _T("txt")
|
|
, fileName
|
|
, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT);
|
|
|
|
if (dlg.DoModal() != IDOK) return;
|
|
|
|
CString sPath(dlg.GetPathName());
|
|
|
|
CFile file(sPath, CFile::modeCreate | CFile::modeWrite | CFile::typeBinary);
|
|
if (file.m_hFile)
|
|
{
|
|
std::string str(CW2A((LPCTSTR)sAnswer, CP_UTF8));
|
|
file.Write(str.c_str(), (UINT)(sizeof(char) * str.length()));
|
|
file.Close();
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void CAskAIPalette::OnBtnClickSend()
|
|
{
|
|
if (hasActiveRequest())
|
|
{
|
|
AfxMessageBox(_T("还有一个问题没有解答完成,请稍等!"));
|
|
return;
|
|
}
|
|
|
|
CString sAsk;
|
|
m_pEdAsk->GetWindowText(sAsk);
|
|
|
|
if (sAsk.IsEmpty())
|
|
{
|
|
AfxMessageBox(_T("消息为空!"));
|
|
return;
|
|
}
|
|
|
|
m_pEdAsk->SetWindowText(_T(""));
|
|
|
|
g_Request.setstream(true);
|
|
|
|
g_Response.clear();
|
|
|
|
CString ss(m_pEdAnswer->GetLineCount() == 1 ? _T("") : _T("\r\n\r\n"));
|
|
sendTextToAnswer(ss + _T("我:\r\n") + sAsk);
|
|
|
|
g_Request.addUserMessage(CW2A((LPCTSTR)sAsk, CP_UTF8));
|
|
|
|
g_hThread = (HANDLE)::_beginthreadex(NULL
|
|
, 0
|
|
, requestSendProc
|
|
, NULL
|
|
, NULL
|
|
, NULL);
|
|
return;
|
|
}
|
|
|
|
void CAskAIPalette::OnBtnClickSetting()
|
|
{
|
|
CAcModuleResourceOverride myResources;
|
|
CAIChatSettingDlg dlg;
|
|
if (dlg.DoModal() == IDOK)
|
|
CAIChatSettingDlg::getChatConfig(m_chatConfig);
|
|
}
|
|
|
|
int CAskAIPalette::OnCreate(LPCREATESTRUCT lpCreateStruct)
|
|
{
|
|
if (CAdUiPalette::OnCreate(lpCreateStruct) == -1)
|
|
return -1;
|
|
|
|
DWORD dwStyle(WS_CHILD | WS_VISIBLE);
|
|
CRect rctmp;
|
|
|
|
do
|
|
{
|
|
m_pEdAnswer = new CEdit();
|
|
if (!m_pEdAnswer->Create(dwStyle
|
|
| ES_MULTILINE
|
|
| ES_AUTOVSCROLL
|
|
| ES_READONLY
|
|
| WS_VSCROLL
|
|
| WS_BORDER
|
|
, rctmp
|
|
, this
|
|
, IDC_EDIT_ANSWER)) break;
|
|
m_pEdAnswer->SetFont(&m_fontEdit);
|
|
|
|
m_pEdAsk = new CEdit();
|
|
if (!m_pEdAsk->Create(dwStyle
|
|
| ES_MULTILINE
|
|
| ES_AUTOVSCROLL
|
|
| ES_WANTRETURN
|
|
| WS_VSCROLL
|
|
| WS_BORDER
|
|
, rctmp
|
|
, this
|
|
, IDC_EDIT_ASK)) break;
|
|
m_pEdAsk->SetFont(&m_fontEdit);
|
|
|
|
m_pBtnNewChat = new CAcUiBitmapButton();
|
|
if (!m_pBtnNewChat->Create(_T("新话题")
|
|
, dwStyle | BS_PUSHBUTTON
|
|
, rctmp
|
|
, this
|
|
, IDC_BTN_NEWCHAT)) break;
|
|
m_pBtnNewChat->SetFont(&m_fontBTN);
|
|
|
|
m_pBtnUploadFile = new CAcUiBitmapButton();
|
|
if (!m_pBtnUploadFile->Create(_T("上传文件")
|
|
, dwStyle | BS_PUSHBUTTON
|
|
, rctmp
|
|
, this
|
|
, IDC_BTN_UPLOAD)) break;
|
|
m_pBtnUploadFile->EnableWindow(FALSE);
|
|
m_pBtnUploadFile->SetFont(&m_fontBTN);
|
|
|
|
m_pBtnTranslate = new CAcUiBitmapButton();
|
|
if (!m_pBtnTranslate->Create(_T("中英互译")
|
|
, dwStyle | BS_PUSHBUTTON
|
|
, rctmp
|
|
, this
|
|
, IDC_BTN_EN2CH)) break;
|
|
m_pBtnTranslate->SetFont(&m_fontBTN);
|
|
|
|
m_pBtnSend = new CAcUiBitmapButton();
|
|
if (!m_pBtnSend->Create(_T("发送(ctrl+Enter)")
|
|
, dwStyle | BS_PUSHBUTTON
|
|
, rctmp
|
|
, this
|
|
, IDC_BTN_SEND)) break;
|
|
m_pBtnSend->SetFont(&m_fontBTN);
|
|
|
|
m_pBtnExport = new CAcUiBitmapButton();
|
|
if (!m_pBtnExport->Create(_T("导出")
|
|
, dwStyle | BS_PUSHBUTTON
|
|
, rctmp
|
|
, this
|
|
, IDC_BTN_EXPORT)) break;
|
|
m_pBtnExport->SetFont(&m_fontBTN);
|
|
|
|
m_pBtnSetting = new CAcUiBitmapButton();
|
|
if (!m_pBtnSetting->Create(_T("设置")
|
|
, dwStyle | BS_PUSHBUTTON
|
|
, rctmp
|
|
, this
|
|
, IDC_BTN_SETTING)) break;
|
|
m_pBtnSetting->SetFont(&m_fontBTN);
|
|
|
|
m_pStaticCloudName = new CStatic();
|
|
if (!m_pStaticCloudName->Create(_T("")
|
|
, dwStyle | SS_RIGHT
|
|
, rctmp
|
|
, this
|
|
, IDC_STATIC)) break;
|
|
m_pStaticCloudName->SetFont(&m_fontBTN);
|
|
|
|
m_pComboModelList = new CAcUiComboBox();
|
|
if (!m_pComboModelList->Create(dwStyle
|
|
| CBS_DROPDOWNLIST
|
|
| WS_VSCROLL
|
|
, CRect(0, 0, 300, 300)
|
|
, this
|
|
, IDC_COMBO_MODEL)) break;
|
|
m_pComboModelList->SetFont(&m_fontBTN);
|
|
|
|
return 0;
|
|
|
|
} while (false);
|
|
|
|
|
|
DELETE_PTR(m_pEdAnswer);
|
|
DELETE_PTR(m_pEdAsk);
|
|
DELETE_PTR(m_pBtnNewChat);
|
|
DELETE_PTR(m_pBtnUploadFile);
|
|
DELETE_PTR(m_pBtnTranslate);
|
|
DELETE_PTR(m_pBtnSend);
|
|
DELETE_PTR(m_pBtnExport);
|
|
DELETE_PTR(m_pStaticCloudName);
|
|
DELETE_PTR(m_pComboModelList);
|
|
|
|
return -1;
|
|
}
|
|
|
|
void CAskAIPalette::OnComboBoxModelListSelChange()
|
|
{
|
|
int idx = m_pComboModelList->GetCurSel();
|
|
if (idx == -1) return;
|
|
|
|
CString sModel;
|
|
m_pComboModelList->GetLBString(idx, sModel);
|
|
|
|
m_pAiCloud->setCurrentModel(AIJSON::w2utf(sModel).c_str());
|
|
g_Request.setmodel(m_pAiCloud->currentModel().c_str());
|
|
CalcCtrlPosition();
|
|
}
|
|
|
|
void CAskAIPalette::OnComboBoxModelListDropDown()
|
|
{
|
|
int iCount = m_pComboModelList->GetCount();
|
|
CString str;
|
|
int len(0);
|
|
CSize sz;
|
|
for (int i(0); i < iCount; ++i)
|
|
{
|
|
m_pComboModelList->GetLBString(i, str);
|
|
sz = getControlWndTextSize(m_pComboModelList, m_fontBTN, str);
|
|
if (len < sz.cx)
|
|
len = sz.cx;
|
|
}
|
|
|
|
int nMin = m_pComboModelList->GetMinVisible();
|
|
m_pComboModelList->SetDroppedWidth(len + (nMin < iCount ? 25 : 5));
|
|
}
|
|
|
|
#define MOVE_WINDOW(wnd,rc) if (wnd && ::IsWindow(wnd->GetSafeHwnd())) wnd->MoveWindow(rc)
|
|
|
|
void CAskAIPalette::CalcCtrlPosition()
|
|
{
|
|
CRect rc;
|
|
GetClientRect(rc);
|
|
rc.InflateRect(-3, -3, -3, -3);
|
|
|
|
int nSpace(3), nAnswerH, nAskH, nBtnH(26), nComboModelsW(300), nStaticCloudH(26);
|
|
int nAllEditH(rc.Height() - nBtnH - 2 * nSpace - nStaticCloudH - 2 * nSpace);
|
|
nAskH = (int)(nAllEditH * .25);
|
|
nAnswerH = nAllEditH - nAskH;
|
|
|
|
CSize csStatic = getControlWndTextSize(m_pStaticCloudName, m_fontBTN);
|
|
|
|
CRect rcStaticCloud(CPoint(rc.left + 1, rc.bottom - nStaticCloudH + 1)
|
|
, CSize(csStatic.cx, nStaticCloudH - 2));
|
|
MOVE_WINDOW(m_pStaticCloudName, rcStaticCloud);
|
|
|
|
CSize csCombo = getControlWndTextSize(m_pComboModelList, m_fontBTN);
|
|
CRect rcComboModels(CPoint(rcStaticCloud.right + 2 * nSpace, rc.bottom - nSpace - nStaticCloudH)
|
|
, CSize(csCombo.cx + 30, nStaticCloudH));
|
|
MOVE_WINDOW(m_pComboModelList, rcComboModels);
|
|
|
|
|
|
CRect rcAsk(CPoint(rc.left, rcComboModels.top - nSpace - nAskH), CSize(rc.Width(), nAskH));
|
|
MOVE_WINDOW(m_pEdAsk, rcAsk);
|
|
|
|
const CSize szBtn(100, nBtnH);
|
|
|
|
int btTop(rcAsk.top - nSpace - szBtn.cy);
|
|
int btBottom(btTop + szBtn.cy);
|
|
|
|
CRect rcNewChat(rc.left, btTop, rc.left + szBtn.cx, btBottom);
|
|
MOVE_WINDOW(m_pBtnNewChat, rcNewChat);
|
|
|
|
CRect rcUpload(rcNewChat.right + 10, btTop, rcNewChat.right + 10 + szBtn.cx, btBottom);
|
|
MOVE_WINDOW(m_pBtnUploadFile, rcUpload);
|
|
|
|
CRect rcEn2Ch(rcUpload.right + 10, btTop, rcUpload.right + 10 + szBtn.cx, btBottom);
|
|
MOVE_WINDOW(m_pBtnTranslate, rcEn2Ch);
|
|
|
|
CRect rcExport(rcEn2Ch.right + 10, btTop, rcEn2Ch.right + 10 + szBtn.cx, btBottom);
|
|
MOVE_WINDOW(m_pBtnExport, rcExport);
|
|
|
|
CRect rcSetting(rcExport.right + 10, btTop, rcExport.right + 10 + szBtn.cx, btBottom);
|
|
MOVE_WINDOW(m_pBtnSetting, rcSetting);
|
|
|
|
CRect rcSend(CPoint(rc.right - 20 - (int)(szBtn.cx * 2), rcComboModels.top)
|
|
, CSize(szBtn.cx * 2, szBtn.cy +4));
|
|
MOVE_WINDOW(m_pBtnSend, rcSend);
|
|
|
|
CRect rcAnswer(rc.TopLeft(), CSize(rc.Width(), nAnswerH));
|
|
MOVE_WINDOW(m_pEdAnswer, rcAnswer);
|
|
|
|
Invalidate();
|
|
}
|
|
|
|
bool CAskAIPalette::hasActiveRequest()
|
|
{
|
|
DWORD dwExitCode;
|
|
BOOL bResult = GetExitCodeThread(g_hThread, &dwExitCode);
|
|
if (bResult && dwExitCode == STILL_ACTIVE)
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
CSize CAskAIPalette::getControlWndTextSize(CWnd *pS, CFont &font, LPCTSTR psz)
|
|
{
|
|
CRect rect;
|
|
CSize size(0, 0);
|
|
CDC *pDc = pS->GetDC();
|
|
|
|
pDc->SelectObject(font);
|
|
|
|
CString str;
|
|
if (psz)
|
|
str = psz;
|
|
else
|
|
pS->GetWindowText(str);
|
|
|
|
::GetTextExtentPoint32(pDc->m_hDC, str, str.GetLength(), &size);
|
|
|
|
pS->ReleaseDC(pDc);
|
|
return size;
|
|
}
|
|
|
|
void CAskAIPalette::OnWindowPosChanged(WINDOWPOS * lpwndpos)
|
|
{
|
|
CAdUiPalette::OnWindowPosChanged(lpwndpos);
|
|
|
|
CalcCtrlPosition();
|
|
}
|
|
|
|
void CAskAIPalette::OnPaint()
|
|
{
|
|
CPaintDC dc(this);
|
|
CRect rc;
|
|
GetClientRect(rc);
|
|
|
|
rc.InflateRect(-2, 0, -2, 0);
|
|
dc.FillSolidRect(rc, RGB(158, 158, 158));
|
|
rc.InflateRect(-1, -1, -1, -1);
|
|
dc.FillSolidRect(rc, RGB(240, 240, 240));
|
|
}
|
|
|
|
void CAskAIPalette::GetFloatingMinSize(long * pnMinWidth, long * pnMinHeight)
|
|
{
|
|
*pnMinWidth = 1023;
|
|
*pnMinHeight = 767;
|
|
}
|
|
|
|
BOOL CAskAIPalette::PreTranslateMessage(MSG *pMsg)
|
|
{
|
|
if (pMsg->message == WM_KEYDOWN)
|
|
{
|
|
CWnd *pWnd = CWnd::FromHandle(pMsg->hwnd);
|
|
if (pWnd->GetDlgCtrlID() == IDC_EDIT_ASK)
|
|
{
|
|
if (pMsg->wParam == VK_RETURN && (GetKeyState(VK_CONTROL) & 0x8000))
|
|
{
|
|
OnBtnClickSend();
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
return CAdUiPalette::PreTranslateMessage(pMsg);
|
|
}
|
|
|
|
bool CAskAIPalette::CanFrameworkTakeFocus()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
|
|
#pragma endregion
|