bool COperMysql::Select(string &dml) { Clear();//清除缓冲 if(mysql_query(m_PtrCon,dml.c_str()) != 0) { //m_Err = mysql_error(m_PtrCon); ZeroMemory(m_szErr, sizeof(m_szErr)); strcpy(m_szErr, mysql_error(m_PtrCon)); TRACE(TEXT(" 操作失败.........")); return false; } m_PtrRes = mysql_store_result(m_PtrCon); //将查询的全部结果读取到客户端 //如果查询未返回结果集 将返回Null指针 //如果读取结果集失败 if (m_PtrCon == NULL) { ZeroMemory(m_szErr, sizeof(m_szErr)); strcpy(m_szErr, mysql_error(m_PtrCon)); //m_Err = mysql_error(m_PtrCon); TRACEA(m_szErr); } m_Row = (WORD)mysql_affected_rows(m_PtrCon); //得到查询返回的行数 MYSQL_FIELD *fieldptr = NULL; //指向 mysql 的查询字段集 while(fieldptr = mysql_fetch_field(m_PtrRes))//取得各字段名和类型 { //从结果集中取得列信息并作为对象返回 typeset_t typeset; typeset.m_index = m_Fieldtype.size(); typeset.m_length = (WORD)fieldptr->length; typeset.m_name = fieldptr->name; typeset.m_type = SetFieldType(fieldptr->type);// m_Fieldtype.push_back(typeset); } MYSQL_ROW currrow = NULL; while((currrow = mysql_fetch_row(m_PtrRes))) //读行的记录 { const unsigned int colcount = mysql_num_fields(m_PtrRes);//取得返回字段的数目 row_t rows(colcount); for(unsigned int i = 0; i < colcount; ++i) { rows[i] = currrow[i] ? currrow[i] : "NULL"; } m_Recordset.push_back(rows); } mysql_free_result(m_PtrRes);//函数释放结果内存 m_PtrRes = NULL; return TRUE; }
int CLameDecoder::GetSkipEnd() { if(m_nPadding > -1) { int ret = m_nPadding - (528 + 1); if(ret < 0) { TRACEA("GetSkipEnd found an abnormal padding value: %d\n", m_nPadding); ret = 0; } return ret; } return 0; }
void *CConnect::GetConObject() { if (m_ptrCon ==NULL) { return NULL; } if (mysql_ping(m_ptrCon) != 0) //自动连接 { //m_sqlerr = mysql_error(m_ptrCon); strcpy(m_szSqlerr, mysql_error(m_ptrCon)); TRACEA(m_szSqlerr); return NULL; } std::cout<<"取得数据库连接!!!"<<endl; return m_ptrCon; }
void SizeToContent(DOCKPANEL *dwp) { RECT rect = { 0,0,0,0 }, rect2; int x = 0, y = 0; if(dwp->hwndPanel == 0 || dwp->hwndContents == 0) return; if(dwp->DockSize.cx == 0 || (dwp->dwStyle & DWS_FIXED_HORZ)) dwp->DockSize.cx = GetWindowWidth(dwp->hwndContents); if(dwp->FloatSize.cx == 0 || (dwp->dwStyle & DWS_FIXED_HORZ)) dwp->FloatSize.cx = GetWindowWidth(dwp->hwndContents); if(dwp->DockSize.cy == 0 || (dwp->dwStyle & DWS_FIXED_VERT)) dwp->DockSize.cy = GetWindowHeight(dwp->hwndContents); if(dwp->FloatSize.cy == 0 || (dwp->dwStyle & DWS_FIXED_VERT)) dwp->FloatSize.cy = GetWindowHeight(dwp->hwndContents); if(dwp->fDocked) { rect.right = dwp->DockSize.cx; rect.bottom = dwp->DockSize.cy; } else { rect.right = dwp->FloatSize.cx; rect.bottom = dwp->FloatSize.cy; } CopyRect(&rect2, &rect); AdjustRectBorders(dwp, &rect, 1); TRACEA("SizeToContent: client=%d %d %d %d adjusted=%d %d %d %d\n", rect2.left, rect2.top, rect2.right, rect2.bottom, rect.left, rect.top, rect.right, rect.bottom ); if(!dwp->fDocked) CalcFloatingRect(dwp->hwndPanel, &rect); SetWindowSize(dwp->hwndPanel, RectWidth(&rect), RectHeight(&rect), NULL); PositionContent(dwp); }
void CloseButton(HDC hdc, RECT *rect, RECT *out, BOOL fHover) { if(out) { out->left = rect->right - 16; out->top = rect->top + 4; out->right = out->left + 13; out->bottom = out->top + 13;//16; } if(hdc) { BOOL fDown = fHover && (GetKeyState(VK_LBUTTON) & 0x80000000); HDC hdcMem = CreateCompatibleDC(hdc); HBITMAP hBmp = CreateBitmap(16, 16, 1, 1, fDown ? CloseButtonDown : CloseButtonBitmapData); HANDLE hOld = SelectObject(hdcMem, hBmp); TRACEA("hot: %d\n", fHover); if(fDown) { SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT)); } else if(fHover) { SetTextColor(hdc, GetSysColor(COLOR_3DDKSHADOW)); } else { SetTextColor(hdc, GetSysColor(COLOR_3DSHADOW)); } //SetBkColor(hdc, colBG); BitBlt(hdc, rect->right - 16, rect->top + 1, 13, 16, hdcMem, 0, 0, SRCCOPY); SelectObject(hdcMem, hOld); DeleteObject(hBmp); DeleteDC(hdcMem); } }
bool COperMysql::Exec(string &ddl) { Clear(); //清除缓冲 if(0 == mysql_query(m_PtrCon,ddl.c_str())) { m_Row = (WORD)mysql_affected_rows(m_PtrCon); //得到受影响的行数 m_SeqID = (WORD)mysql_insert_id(m_PtrCon); } else { ZeroMemory(m_szErr, sizeof(m_szErr)); strcpy(m_szErr, mysql_error(m_PtrCon)); //m_Err = mysql_error(m_PtrCon); TRACEA(m_szErr); return FALSE; } return TRUE; }
DWORD CALLBACK TaskThreadProc(LPVOID ThreadParam) { NSIS::stack_t *pURL,*pFile; HINTERNET hInetSes = NULL, hInetCon = NULL; HANDLE hLocalFile; bool completedFile = false; startnexttask: hLocalFile = INVALID_HANDLE_VALUE; pFile = NULL; TaskLock_AcquireExclusive(); // Now that we've acquired the lock, we can set the event to indicate this. // SetEvent will likely never fail, but if it does we should set it to NULL // to avoid anyone waiting on it. if (!SetEvent(g_hGETStartedEvent)) { CloseHandle(g_hGETStartedEvent); g_hGETStartedEvent = NULL; } pURL = g_pLocations; if (pURL) { pFile = pURL->next; g_pLocations = pFile->next; } #ifndef ONELOCKTORULETHEMALL StatsLock_AcquireExclusive(); #endif if (completedFile) { ++g_FilesCompleted; } completedFile = false; g_cbCurrXF = 0; g_cbCurrTot = FILESIZE_UNKNOWN; if (!pURL) { if (g_FilesTotal) { if (g_FilesTotal == g_FilesCompleted) { g_Status = STATUS_COMPLETEDALL; } } g_hThread = NULL; } #ifndef ONELOCKTORULETHEMALL StatsLock_ReleaseExclusive(); #endif TaskLock_ReleaseExclusive(); if (!pURL) { if (0) { diegle: DWORD gle = GetLastError(); //TODO? if (ERROR_INTERNET_EXTENDED_ERROR==gle) InternetGetLastResponseInfo(...) g_Status = STATUS_ERR_GETLASTERROR; } if (hInetSes) { InternetCloseHandle(hInetSes); } if (hInetCon) { InternetCloseHandle(hInetCon); } if (INVALID_HANDLE_VALUE != hLocalFile) { CloseHandle(hLocalFile); } StackFreeItem(pURL); StackFreeItem(pFile); return 0; } if (!hInetSes) { hInetSes = InternetOpen(USERAGENT, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); if (!hInetSes) { goto diegle; } //msdn.microsoft.com/library/default.asp?url=/workshop/components/offline/offline.asp#Supporting Offline Browsing in Applications and Components ULONG longOpt; DWORD cbio = sizeof(ULONG); if (InternetQueryOption(hInetSes, INTERNET_OPTION_CONNECTED_STATE, &longOpt, &cbio)) { if (INTERNET_STATE_DISCONNECTED_BY_USER&longOpt) { INTERNET_CONNECTED_INFO ci = {INTERNET_STATE_CONNECTED, 0}; InternetSetOption(hInetSes, INTERNET_OPTION_CONNECTED_STATE, &ci, sizeof(ci)); } } if(g_ConnectTimeout > 0) { InternetSetOption(hInetSes, INTERNET_OPTION_CONNECT_TIMEOUT, &g_ConnectTimeout, sizeof(g_ConnectTimeout)); } } DWORD ec = ERROR_SUCCESS; hLocalFile = CreateFile(pFile->text,GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_DELETE,NULL,CREATE_ALWAYS,0,NULL); if (INVALID_HANDLE_VALUE == hLocalFile) { goto diegle; } const DWORD IOURedirFlags = INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP | INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS; const DWORD IOUCacheFlags = INTERNET_FLAG_RESYNCHRONIZE | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_RELOAD; const DWORD IOUCookieFlags = INTERNET_FLAG_NO_COOKIES; DWORD IOUFlags = IOURedirFlags | IOUCacheFlags | IOUCookieFlags | INTERNET_FLAG_NO_UI | INTERNET_FLAG_EXISTING_CONNECT; WCHAR protocol[16]; WCHAR server[128]; WCHAR path[1024]; INTERNET_PORT port; // Good old VC6 cannot deduce the size of these params :'( if (!BasicParseURL<16, 128, 1024>(pURL->text, &protocol, &port, &server, &path)) { // Insufficient buffer or bad URL passed in goto diegle; } DWORD context; hInetCon = InternetConnect(hInetSes, server, port, NULL, NULL, INTERNET_SERVICE_HTTP, IOUFlags, (unsigned long)&context); if (!hInetCon) { goto diegle; } // Setup a buffer of size 256KiB to store the downloaded data. // Get at most 4MiB at a time from the partial HTTP Range requests. // Biffer buffers will be faster. // cbRangeReadBufXF should be a multiple of cbBufXF. const UINT cbBufXF = 262144; const UINT cbRangeReadBufXF = 4194304; BYTE bufXF[cbBufXF]; // Up the default internal buffer size from 4096 to internalReadBufferSize. DWORD internalReadBufferSize = cbRangeReadBufXF; if (!InternetSetOption(hInetCon, INTERNET_OPTION_READ_BUFFER_SIZE, &internalReadBufferSize, sizeof(DWORD))) { // Maybe it's too big, try half of the optimal value. If that fails just // use the default. internalReadBufferSize /= 2; InternetSetOption(hInetCon, INTERNET_OPTION_READ_BUFFER_SIZE, &internalReadBufferSize, sizeof(DWORD)); } // Change the default timeout of 30 seconds to the specified value. // Is case a proxy in between caches the results, it could in theory // take longer to get the first chunk, so it is good to set this high. if (g_ReceiveTimeout) { InternetSetOption(hInetCon, INTERNET_OPTION_DATA_RECEIVE_TIMEOUT, &g_ReceiveTimeout, sizeof(DWORD)); } HINTERNET hInetFile; DWORD cbio = sizeof(DWORD); // Keep looping until we don't have a redirect anymore int redirectCount = 0; for (;;) { // Make sure we aren't stuck in some kind of infinite redirect loop. if (redirectCount > 15) { goto diegle; } // If a range request was specified, first do a HEAD request hInetFile = HttpOpenRequest(hInetCon, g_WantRangeRequest ? L"HEAD" : L"GET", path, NULL, NULL, NULL, INTERNET_FLAG_NO_AUTO_REDIRECT | INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_RELOAD, 0); if (!hInetFile) { goto diegle; } if (!HttpSendRequest(hInetFile, NULL, 0, NULL, 0)) { goto diegle; } WCHAR responseText[256]; cbio = sizeof(responseText); if (!HttpQueryInfo(hInetFile, HTTP_QUERY_STATUS_CODE, responseText, &cbio, NULL)) { goto diegle; } int statusCode = _wtoi(responseText); if (statusCode == HTTP_STATUS_REDIRECT || statusCode == HTTP_STATUS_MOVED) { redirectCount++; WCHAR URLBuffer[2048]; cbio = sizeof(URLBuffer); if (!HttpQueryInfo(hInetFile, HTTP_QUERY_LOCATION, (DWORD*)URLBuffer, &cbio, NULL)) { goto diegle; } WCHAR protocol2[16]; WCHAR server2[128]; WCHAR path2[1024]; INTERNET_PORT port2; BasicParseURL<16, 128, 1024>(URLBuffer, &protocol2, &port2, &server2, &path2); // Check if we need to reconnect to a new server if (wcscmp(protocol, protocol2) || wcscmp(server, server2) || port != port2) { wcscpy(server, server2); port = port2; InternetCloseHandle(hInetCon); hInetCon = InternetConnect(hInetSes, server, port, NULL, NULL, INTERNET_SERVICE_HTTP, IOUFlags, (unsigned long)&context); if (!hInetCon) { goto diegle; } } wcscpy(path, path2); // Close the existing handle because we'll be issuing a new request // with the new request path. InternetCloseHandle(hInetFile); continue; } break; } // Get the file length via the Content-Length header FILESIZE_T cbThisFile; cbio = sizeof(cbThisFile); if (!HttpQueryInfo(hInetFile, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &cbThisFile, &cbio, NULL)) { cbThisFile = FILESIZE_UNKNOWN; } // Determine if we should use byte range requests. We want to use it if: // 1. Server accepts byte range requests // 2. The size of the file is known and more than our Range buffer size. bool shouldUseRangeRequest = true; WCHAR rangeRequestAccepted[64] = { '\0' }; cbio = sizeof(rangeRequestAccepted); if (cbThisFile != FILESIZE_UNKNOWN && cbThisFile <= cbRangeReadBufXF || !HttpQueryInfo(hInetFile, HTTP_QUERY_ACCEPT_RANGES, (LPDWORD)rangeRequestAccepted, &cbio, NULL)) { shouldUseRangeRequest = false; } else { shouldUseRangeRequest = wcsstr(rangeRequestAccepted, L"bytes") != 0 && cbThisFile != FILESIZE_UNKNOWN; } // If the server doesn't have range request support or doesn't have a // Content-Length header, then get everything all at once. // If the user didn't want a range request, then we already issued the GET // request earlier. If the user did want a range request, then we issued only // a HEAD so far. if (g_WantRangeRequest && !shouldUseRangeRequest) { InternetCloseHandle(hInetFile); InternetCloseHandle(hInetCon); hInetFile = InternetOpenUrl(hInetSes, pURL->text, NULL, 0, IOUFlags, NULL); if (!hInetFile) { goto diegle; } // For some reason this also needs to be set on the hInetFile and // not just the connection. if (g_ReceiveTimeout > 0) { InternetSetOption(hInetCon, INTERNET_OPTION_DATA_RECEIVE_TIMEOUT, &g_ReceiveTimeout, sizeof(DWORD)); } } for(;;) { DWORD cbio = 0,cbXF = 0; // If we know the file size, download it in chunks if (g_WantRangeRequest && shouldUseRangeRequest && cbThisFile != g_cbCurrXF) { // Close the previous request, but not the connection InternetCloseHandle(hInetFile); hInetFile = HttpOpenRequest(hInetCon, L"GET", path, NULL, NULL, NULL, INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_RELOAD, 0); if (!hInetFile) { // TODO: we could add retry here to be more tolerant goto diegle; } // For some reason this also needs to be set on the hInetFile and // not just the connection. if (g_ReceiveTimeout > 0) { InternetSetOption(hInetCon, INTERNET_OPTION_DATA_RECEIVE_TIMEOUT, &g_ReceiveTimeout, sizeof(DWORD)); } WCHAR range[32]; swprintf(range, L"Range: bytes=%d-%d", g_cbCurrXF, min(g_cbCurrXF + cbRangeReadBufXF, cbThisFile)); if (!HttpSendRequest(hInetFile, range, wcslen(range), NULL, 0)) { // TODO: we could add retry here to be more tolerant goto diegle; } } // Read the chunk (or full file if we don't know the size) we downloaded BOOL retXF; for (;;) { DWORD cbioThisIteration = 0; retXF = InternetReadFile(hInetFile, bufXF, cbBufXF, &cbioThisIteration); if (!retXF) { ec = GetLastError(); TRACE1(_T("InternetReadFile failed, gle=%u\n"), ec); // TODO: we could add retry here to be more tolerant goto diegle; } // Check if we're done reading if (cbioThisIteration == 0) { break; } // Write what we found cbXF = cbioThisIteration; retXF = WriteFile(hLocalFile, bufXF, cbXF, &cbioThisIteration, NULL); if (!retXF || cbXF != cbioThisIteration) { cbio += cbioThisIteration; ec = GetLastError(); break; } cbio += cbioThisIteration; StatsLock_AcquireExclusive(); if (FILESIZE_UNKNOWN != cbThisFile) { g_cbCurrTot = cbThisFile; } g_cbCurrXF += cbXF; StatsLock_ReleaseExclusive(); // Avoid an extra call to InternetReadFile if we already read everything // in the current request if (cbio == cbRangeReadBufXF && shouldUseRangeRequest) { break; } } // Check if we're done transferring the file successfully if (0 == cbio && (cbThisFile == FILESIZE_UNKNOWN || cbThisFile == g_cbCurrXF)) { ASSERT(ERROR_SUCCESS == ec); TRACE2(_T("InternetReadFile true with 0 cbio, cbThisFile=%d gle=%u\n"), cbThisFile, GetLastError()); break; } // Check if we canceled the download if (0 == g_FilesTotal) { TRACEA("0==g_FilesTotal, aborting transfer loop...\n"); ec = ERROR_CANCELLED; break; } } TRACE2(_T("TaskThreadProc completed %s, ec=%u\n"), pURL->text, ec); InternetCloseHandle(hInetFile); if (ERROR_SUCCESS == ec) { if (INVALID_HANDLE_VALUE != hLocalFile) { CloseHandle(hLocalFile); hLocalFile = INVALID_HANDLE_VALUE; } StackFreeItem(pURL); StackFreeItem(pFile); ++completedFile; } else { SetLastError(ec); goto diegle; } goto startnexttask; }
LRESULT HexEdit_OnNotify(MAINWND *mainWnd, HWND hwnd, UINT idCtrl, NMHDR *hdr) { HWND hwndHV = GetActiveHexView(hwnd); if(hdr->hwndFrom == mainWnd->hwndTabView) { TCITEM tci = { TCIF_PARAM }; TabCtrl_GetItem(mainWnd->hwndTabView, TabCtrl_GetCurSel(mainWnd->hwndTabView), &tci); // has the user clicked a file-tab? if(hdr->code == TCN_SELCHANGE) { HexSetCurFile(hwnd, TabCtrl_GetCurSel(mainWnd->hwndTabView), TRUE); OnFileChange(mainWnd); return 0; } else if(hdr->code == TCN_CLOSING) { // prompt close if if(HexFileCloseNotify(hwnd, hwndHV) == IDCANCEL) return TRUE; return 0; } else if(hdr->code == TCN_CLOSE) { // ask user if they want to save changes if(HexFileCloseNotify(hwnd, hwndHV) == IDCANCEL) return 0; //SetCurFile(hwnd, TabCtrl_GetCurSel(mainWnd->hwndTabView)); //DestroyWindow((HWND)tci.lParam); HexCloseFile(mainWnd, TabCtrl_GetCurSel(mainWnd->hwndTabView)); return 0; } } // double-click in a statusbar pane? if(hdr->hwndFrom == mainWnd->hwndStatusBar && hdr->code == NM_DBLCLK) { NMMOUSE *nmmouse; // statusbar is the only window at present which sends double-clicks nmmouse = (NMMOUSE *)hdr; // toggle the Readonly/Insert/Overwrite mode if(nmmouse->dwItemSpec == 4) { ToggleEditorMode(hwndHV); UpdateStatusBarText(mainWnd->hwndStatusBar, hwndHV); } return 0; } if(hdr->code == TBN_DROPDOWN) { if(GetParent(hdr->hwndFrom) == mainWnd->hwndStatusBar) { StatusBar_DropDownTB(mainWnd, hwndHV, (NMTOOLBAR *)hdr); } if(hdr->hwndFrom == mainWnd->hwndToolbar) { HexPasteSpecialDlg2(hwnd); } return 0; } /* if(hdr->code == DWN_ISDOCKABLE) { RECT rc1, rc2; // Get main window "outer" rectangle GetWindowRect(hwnd, &rc1); // Get main window "inner" rectangle GetClientRect(hwnd, &rc2); MapWindowPoints(hwnd, 0, (POINT *)&rc2, 2); InflateRect(&rc2, -2, -2); return DockWnd_GetDockSide(hwnd, (NMDOCKWNDQUERY *)hdr, &rc1, &rc2); }*/ if(hdr->code == DWN_SAVESETTINGS) { NMDOCKWNDCREATE *nmdw = (NMDOCKWNDCREATE *)hdr; TRACEA(" DWN_SAVESETTINGS: %d\n", nmdw->uId); switch(nmdw->hdr.idFrom) { case DWID_TYPEVIEW: case DWID_ALLTYPES: SaveTypeView(nmdw->hwndClient, nmdw->hKey); break; } return 0; } if(hdr->code == DWN_UPDATE_CONTENT) { NMDOCKWND *nmdw = (NMDOCKWND *)hdr; HWND hwndHV = GetActiveHexView(hwnd); switch(nmdw->hdr.idFrom) { case DWID_HIGHLIGHT: UpdateHighlights(TRUE); break; } return 0; } if(hdr->code == DWN_CREATE_CONTENT) { NMDOCKWNDCREATE *nmdw = (NMDOCKWNDCREATE *)hdr; TRACEA("DWN_CREATE_CONTENT: %d\n", hdr->idFrom); switch(nmdw->hdr.idFrom) { case DWID_TOOLBAR: mainWnd->hwndToolbar = InitToolbar(hdr->hwndFrom); return (LONG)mainWnd->hwndToolbar; case DWID_SEARCHBAR: return (LONG)CreateSearchBar(hdr->hwndFrom); case DWID_ALLTYPES: //SendMessage(hwndTB, TB_SETSTATE, IDM_TOOLS_TYPEVIEW, DockWnd_IsOpen(g_hwndMain, DWID_TYPEVIEW) ? TBSTATE_CHECKED|TBSTATE_ENABLED : TBSTATE_ENABLED); return (LONG)CreateTypeView(hdr->hwndFrom, nmdw->hKey, TRUE);//TEXT("struct ALL")); case DWID_TYPEVIEW: //SendMessage(hwndTB, TB_SETSTATE, IDM_TOOLS_TYPEVIEW, DockWnd_IsOpen(g_hwndMain, DWID_TYPEVIEW) ? TBSTATE_CHECKED|TBSTATE_ENABLED : TBSTATE_ENABLED); return (LONG)CreateTypeView(hdr->hwndFrom, nmdw->hKey, 0); case DWID_HIGHLIGHT: return (LONG)CreateHighlightView(hdr->hwndFrom); case DWID_STRINGS: return (LONG)CreateStringsView(hdr->hwndFrom); } } else if(hdr->code == DWN_DOCKCHANGE) { NMDOCKWND *nmdw = (NMDOCKWND *)hdr; switch(nmdw->hdr.idFrom) { case DWID_TOOLBAR: SendMessage(DockWnd_GetContents(mainWnd->hwndMain, DWID_TOOLBAR), TB_SETPARENT, (WPARAM)hdr->hwndFrom, 0); return 0; } } else if(hdr->code == DWN_CLOSING) { NMDOCKWND *nmdw = (NMDOCKWND *)hdr; switch(nmdw->hdr.idFrom) { case DWID_TYPEVIEW: break; } return 0; } return DefWindowProc(hwnd, WM_NOTIFY, idCtrl, (LONG)hdr); }
BOOL UpdateProgress(MAINWND *mainWnd, BOOL fVisible, size_w pos, size_w len) { MSG msg; BOOL fAbort = FALSE; int newpos = len > 0 ? (int)((UINT64)pos*100/len) : 0;//(unsigned __int64)256) / len); DWORD dwRate; static HWND hwndProgress; static DWORD startTicks; static DWORD lastTick; static size_w oldpos; static size_w startpos; if(fVisible == FALSE) { DestroyWindow(hwndProgress); SetStatusBarText(mainWnd->hwndStatusBar, 0, 1, TEXT("")); return FALSE; } // create the progress window if it's not been done already if(hwndProgress == 0) { RECT rect; SendMessage(mainWnd->hwndStatusBar, SB_GETRECT, 0, (LPARAM)&rect); hwndProgress = CreateWindowEx(0, PROGRESS_CLASS, 0, WS_CHILD|WS_VISIBLE, rect.left+220,rect.top+2, min(rect.right-rect.left-220,159),rect.bottom-rect.top-5, mainWnd->hwndStatusBar, 0, 0, 0); SendMessage(hwndProgress, PBM_SETRANGE, 0, MAKELPARAM(0, 100)); startTicks = GetTickCount(); oldpos = 0; startpos = pos; } if(GetTickCount() - lastTick > 1000) { lastTick = GetTickCount(); dwRate = (lastTick - startTicks) / 1000; TRACEA("search: searched=%d elapsed=%d (%u/%u -> %d)\n", pos-oldpos, dwRate, pos, len, newpos); dwRate = (DWORD)(dwRate ? ((pos-startpos)/(1024*1024)) / dwRate : 0); //dwRate = dwRate / (1024 * 1024); SetStatusBarText(mainWnd->hwndStatusBar, 0, 1, TEXT("%s: %d Mb/s"), TEXT("Searching"), dwRate); } SendMessage(hwndProgress, PBM_SETPOS, newpos, 0); // dispatch any messages while(!fAbort && PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); switch(msg.message) { case WM_QUIT: PostQuitMessage(0); fAbort = TRUE; break; case WM_KEYDOWN: if(msg.wParam == VK_ESCAPE) { fAbort = TRUE; //fAbort = QueryAbortDlg(); continue; } break; case WM_LBUTTONDOWN : case WM_RBUTTONDOWN: case WM_MBUTTONDOWN: //fAbort = QueryAbortDlg(); fAbort = TRUE; continue; } DispatchMessage(&msg); } oldpos = pos; return fAbort; }
void JobThreadFunc(void) { Lock(); O2IMessages queue(Queue); Queue.clear(); Unlock(); if (queue.size() == 0) return; hashT myid; Profile->GetID(myid); O2IMessagesIt it; for (it = queue.begin(); it != queue.end() && IsActive(); it++) { O2IMessage &im = *it; TRACEA("[BroadcastJob]"); TRACEW(it->msg.c_str()); TRACEA("\n"); O2NodeDB::NodeListT neighbors; if (NodeDB->neighbors(myid, neighbors, false, O2_BROADCAST_PATH_LIMIT+2) == 0) return; O2NodeDB::NodeListT::iterator nit = neighbors.begin(); while (nit != neighbors.end()) { if (nit->id == im.id) { nit = neighbors.erase(nit); continue; } hashListT::iterator hit = std::find(im.paths.begin(), im.paths.end(), nit->id); if (hit != im.paths.end()) { nit = neighbors.erase(nit); continue; } nit++; } if (neighbors.empty()) continue; hashT myid; Profile->GetID(myid); im.paths.push_back(myid); while (im.paths.size() > O2_BROADCAST_PATH_LIMIT) im.paths.pop_front(); for (nit = neighbors.begin(); nit != neighbors.end() && IsActive(); nit++) { nit->lastlink = 0; nit->reset(); // Broadcast発行 O2SocketSession ss; ss.ip = nit->ip; ss.port = nit->port; string xml; BroadcastDB->MakeSendXML(im, xml); string url; MakeURL(ss.ip, ss.port, O2PROTOPATH_BROADCAST, url); HTTPHeader hdr(HTTPHEADERTYPE_REQUEST); hdr.method = "POST"; hdr.SetURL(url.c_str()); AddRequestHeaderFields(hdr, Profile); AddContentFields(hdr, xml.size(), "text/xml", DEFAULT_XML_CHARSET); hdr.Make(ss.sbuff); ss.sbuff += xml; Client->AddRequest(&ss); ss.Wait(); HTTPHeader *header = (HTTPHeader*)ss.data; if (CheckResponse(&ss, header, NodeDB, *nit)) { ; } if (header) delete header; Sleep(1000); } for (nit = neighbors.begin(); nit != neighbors.end() && IsActive(); nit++) { if (nit->lastlink) { // 成功したノードをtouch NodeDB->touch(*nit); } else { // 失敗したノードをremove NodeDB->remove(*nit); KeyDB->DeleteKeyByNodeID(nit->id); } } Sleep(IsActive() ? 1000 : 0); } }
uint O2Agent:: NetIOThread(void) { O2SocketSessionListIt ssit; int lasterror; while (Active) { //setup FD fd_set readfds; fd_set writefds; FD_ZERO(&readfds); FD_ZERO(&writefds); //wait Lock(); uint n = sss.size(); Unlock(); if (n == 0) { ResetEvent(SessionAvailableEvent); } WaitForSingleObject(SessionAvailableEvent, INFINITE); if (!Active) break; //FD Lock(); for (ssit = sss.begin(); ssit != sss.end(); ssit++) { O2SocketSession *ss = *ssit; if (!ss->sendcomplete) FD_SET(ss->sock, &writefds); else FD_SET(ss->sock, &readfds); } Unlock(); //select struct timeval tv; tv.tv_sec = SELECT_TIMEOUT_MS/1000; tv.tv_usec = SELECT_TIMEOUT_MS%1000; select(0, &readfds, &writefds, NULL, &tv); // // 既存セッションとの送受信 // Lock(); ssit = sss.begin(); Unlock(); while (1) { bool loopend = false; Lock(); if (ssit == sss.end()) loopend = true; Unlock(); if (loopend) break; #if DEBUG_THREADLOOP && defined(_DEBUG) TRACEA("[NetIO]\n"); #endif O2SocketSession *ss = *ssit; O2AgentService *service = (O2AgentService*)ss->service; ushort port = htons(ss->sin.sin_port); wstring ipstr; #if defined (_DEBUG) ulong2ipstr(ss->sin.sin_addr.S_un.S_addr, ipstr); #else ip2e(ss->sin.sin_addr.S_un.S_addr, ipstr); #endif //send if (FD_ISSET(ss->sock, &writefds)) { int len; const char *buff = ss->GetSendBuffer(len); if (len > 0) { int n = send(ss->sock, buff, len, 0); #if DEBUG_THREADLOOP && defined(_DEBUG) TRACEA("[A]send\n"); #endif if (n > 0) { ss->UpdateSend(n); NodeDB->IncrementSendByte_me2n(ss->sin.sin_addr.S_un.S_addr, n); service->IncrementSendByte(n); service->OnSend(ss); ss->UpdateTimer(); if (hwndSetIconCallback) { PostMessage(hwndSetIconCallback, msgSetIconCallback, 1, 0); } } else if (n == 0) { ; } else if ((lasterror = WSAGetLastError()) != WSAEWOULDBLOCK) { if (Logger) { Logger->AddLog(O2LT_NET, MODULE, L"送信エラー(%d) (%s %s:%d %dbyte)", lasterror, service->GetName(), ipstr.c_str(), port, ss->sbuff.size()); } ss->SetActive(false); } } } //recv if (FD_ISSET(ss->sock, &readfds)) { char buff[RECVBUFFSIZE]; int n = recv(ss->sock, buff, RECVBUFFSIZE, 0); #if DEBUG_THREADLOOP && defined(_DEBUG) TRACEA("[A]recv\n"); #endif if (n > 0) { ss->AppendRecv(buff, n); NodeDB->IncrementRecvByte_me2n(ss->sin.sin_addr.S_un.S_addr, n); service->IncrementRecvByte(n); service->OnRecv(ss); ss->UpdateTimer(); if (hwndSetIconCallback) { PostMessage(hwndSetIconCallback, msgSetIconCallback, 0, 0); } } else if (n == 0) { if (Logger) { Logger->AddLog(O2LT_NET, MODULE, L"受信0 (%s %s:%d)", service->GetName(), ipstr.c_str(), port); } ss->SetActive(false); } else if ((lasterror = WSAGetLastError()) != WSAEWOULDBLOCK) { if (Logger) { Logger->AddLog(O2LT_NET, MODULE, L"受信エラー(%d) (%s %s:%d %dbyte)", lasterror, service->GetName(), ipstr.c_str(), port, ss->rbuff.size()); } ss->SetActive(false); } } //delete if (!ss->IsActive() || ss->GetPastTime() >= SOCKET_TIMEOUT_S) { void *databk = ss->data; ulong ip = ss->sin.sin_addr.S_un.S_addr; closesocket(ss->sock); service->OnClose(ss); NodeDB->RemoveStatusBit(ip, O2_NODESTATUS_LINKEDTO); NodeDB->AddStatusBit(ip, O2_NODESTATUS_PASTLINKEDTO); service->DecrementCount(); if (!ss->rbuff.empty() && !ss->sbuff.empty()) { NodeDB->UpdateLastModified(ip, 2); service->IncrementTotalSessionCount(); } else if (ss->rbuff.empty()) NodeDB->IncrementErrorCount(ip, 1); if (!ss->rbuff.empty() && (!databk || ss->rbuff[0] != 'H')) { NodeDB->DeleteNode(ip); if (Logger) { Logger->AddLog(O2LT_WARNING, MODULE, L"不正データ受信 (ノード削除: %s:%d)", ipstr.c_str(), htons(ss->sin.sin_port)); } if (O2DEBUG) { char filename[256]; sprintf_s(filename, 256, "dump\\A_%d.txt", rand()); FILE *fp; fopen_s(&fp, filename, "wb"); fwrite(ss->rbuff.c_str(), ss->rbuff.size(), 1, fp); fclose(fp); } } #if DEBUG_SESSION_COUNT && defined(_DEBUG) wchar_t abc[256]; swprintf(abc, L"■■削除■■ count:%d limit:%d %s\n", service->GetSessionCount(), service->GetSessionLimit(), service->GetName()); TRACEW(abc); #endif Lock(); ssit = sss.erase(ssit); Unlock(); delete ss; continue; } Sleep(1); ssit++; } } //end Lock(); for (ssit = sss.begin(); ssit != sss.end(); ssit++) { O2SocketSession *ss = *ssit; closesocket(ss->sock); ss->sock = 0; ((O2AgentService*)((O2AgentService*)ss->service))->OnClose(ss); delete ss; } sss.clear(); Unlock(); return (0); }
uint O2Agent:: LaunchThread(void) { for (uint i = 0; i < Services.size(); i++) { Services[i]->SetActive(true); Services[i]->OnServiceStart(); } Agent_GetGlobalIP->SetActive(true); Agent_GetGlobalIP->OnServiceStart(); if (Logger) Logger->AddLog(O2LT_INFO, MODULE, L"エージェント正常起動"); time_t prevconnecttime = time(NULL); uint index = 0; while (Active) { index %= Services.size(); /* * ウェイト処理 */ if (NodeDB->Count() == 0) { #if DEBUG_THREADLOOP && defined(_DEBUG) TRACEA("■Node 0\n"); #endif Sleep(1000); continue; } uint pasttime_ms = ((uint)time(NULL) - (uint)prevconnecttime) * 1000; if (pasttime_ms < Interval) { uint sleeptime_ms = Interval - pasttime_ms; #if DEBUG_THREADLOOP && defined(_DEBUG) TRACEA("Wait interval\n"); #endif if (Agent_GetGlobalIP->IsActive()) { ; //グローバルIP未確定のときは急ぐ } else { if (sleeptime_ms < 1000) Sleep(sleeptime_ms); else Sleep(1000); continue; } } /* * サービス起動 */ O2AgentService *service = Services[index]; if (Agent_GetGlobalIP->IsActive()) //グローバルIP未決定のとき service = Agent_GetGlobalIP; //強制的にAgent_GetGlobalIP起動 #if DEBUG_SESSION_COUNT && defined(_DEBUG) wchar_t abc[256]; swprintf(abc, L"● count:%d limit:%d %s\n", service->GetSessionCount(), service->GetSessionLimit(), service->GetName()); TRACEW(abc); #endif if (!service->IsActive()) { index++; continue; } if (service->GetSessionCount() >= service->GetSessionLimit()) { Sleep(500); index++; continue; } O2SocketSession *ss = new O2SocketSession(); ss->service = (void*)service; ulong ip; ushort port; wstring ipstr; //接続先ノード決定 //接続 TODO:クラスタリング if (service->HaveNodeDecision()) { service->OnLaunch(ss); if (!ss->IsActive()) { delete ss; index++; continue; } ip = ss->sin.sin_addr.S_un.S_addr; port = htons(ss->sin.sin_port); } else if (!NodeDB->GetNodeByPriority(ip, port)) { if (Logger) { Logger->AddLog(O2LT_WARNING, MODULE, L"有効なノード情報が無いので接続不可(%s)", service->GetName()); } delete ss; index++; continue; } #if !defined(_DEBUG) if (ip == Profile->GetIP() || ip == 0x0100007f) { #if 0 struct in_addr addr; addr.S_un.S_addr = ip; if (Logger) { Logger->AddLog(O2LT_WARNING, MODULE, "自ノード情報破棄 IP: %s Port: %d", inet_ntoa(addr), port); } #endif NodeDB->DeleteNode(ip); delete ss; index++; continue; } #endif #if defined(_DEBUG) ulong2ipstr(ip, ipstr); #else ip2e(ip, ipstr); #endif /* * Socket生成 */ ss->sock = socket(AF_INET, SOCK_STREAM, 0); if (ss->sock == INVALID_SOCKET) { if (Logger) Logger->AddLog(O2LT_ERROR, MODULE, L"ソケット生成に失敗"); delete ss; index++; continue; } ss->sin.sin_family = AF_INET; ss->sin.sin_port = htons(port); ss->sin.sin_addr.S_un.S_addr = ip; /* * Connect */ int timeout = service == Agent_GetGlobalIP ? GIP_CONNECT_TIMEOUT_MS : CONNECT_TIMEOUT_MS; if (connect2(ss->sock, (struct sockaddr*)&ss->sin, sizeof(ss->sin), timeout) != 0) { //NodeDB->DeleteNode(ip); NodeDB->IncrementErrorCount(ip, 1); if (Logger) { Logger->AddLog(O2LT_NET, MODULE, L"connect失敗(%s %s:%d)", service->GetName(), ipstr.c_str(), port); } closesocket(ss->sock); delete ss; index++; continue; } if (hwndSetIconCallback) { PostMessage(hwndSetIconCallback, msgSetIconCallback, 1, 0); } //launch if (!service->HaveNodeDecision()) { service->OnLaunch(ss); if (!ss->IsActive()) { closesocket(ss->sock); delete ss; index++; continue; } } ss->UpdateTimer(); service->IncrementCount(); Lock(); sss.push_back(ss); Unlock(); SetEvent(SessionAvailableEvent); NodeDB->AddStatusBit(ip, O2_NODESTATUS_LINKEDTO); prevconnecttime = time(NULL); index++; #if DEBUG_SESSION_COUNT && defined(_DEBUG) swprintf(abc, L"●● count:%d limit:%d %s\n", service->GetSessionCount(), service->GetSessionLimit(), service->GetName()); TRACEW(abc); #endif if (Logger) { Logger->AddLog(O2LT_NET, MODULE, L"connect成功 (%s %s:%d)", service->GetName(), ipstr.c_str(), port); } } //end Lock(); SetEvent(SessionAvailableEvent); Unlock(); for (uint i = 0; i < Services.size(); i++) { O2AgentService *service = Services[i]; if (service->IsActive()) { service->SetActive(false); service->OnServiceEnd(); } } if (Logger) Logger->AddLog(O2LT_INFO, MODULE, L"エージェント正常終了"); return (0); }
int CLameDecoder::Decode1Frame(unsigned char* mp3buf, size_t len, short pcm_l[], short pcm_r[], mp3data_struct* mp3data) { if(!m_bSkipPadding) { return Decode1FrameRaw(mp3buf, len, pcm_l, pcm_r, mp3data); } else { int ret = -1; if(m_pDelayInfo == NULL) { ret = Decode1FrameRaw(mp3buf, len, pcm_l, pcm_r, mp3data); //found nc_delay and enc_padding, and have some decoded data //this case should not happen in normal case if(ret > 0 && m_pDelayInfo != NULL) { assert(m_pDelayInfo->pBufferL != NULL); TRACEA("[abnormal]: m_pDelayInfo != NULL. ret=%d\n", ret); m_pDelayInfo->pBufferL->AddData((char*)pcm_l, 2, ret); m_pDelayInfo->pBufferR->AddData((char*)pcm_r, 2, ret); } else { return ret; } } else { short *bufferL = (short*)m_pDelayInfo->pBufferL->GetBuffer(MAX_SAMPLES_PER_FRAME); short *bufferR = (short*)m_pDelayInfo->pBufferR->GetBuffer(MAX_SAMPLES_PER_FRAME); assert(bufferL != NULL && bufferR != NULL); ret = Decode1FrameRaw(mp3buf, len, bufferL, bufferR, mp3data); int nNewData = (ret < 0 ? 0 : ret); m_pDelayInfo->pBufferL->ReleaseBuffer(MAX_SAMPLES_PER_FRAME, nNewData); m_pDelayInfo->pBufferR->ReleaseBuffer(MAX_SAMPLES_PER_FRAME, nNewData); if(ret <= 0) { return ret; } } assert(ret > 0 && m_pDelayInfo != NULL); int nLeft; //start skip nLeft = GetSkipStart() - m_pDelayInfo->nStartSkipped; if(nLeft > 0) { if(nLeft >= ret) { TRACEA("Skipped the current whole block: %d\n", ret); m_pDelayInfo->nStartSkipped += ret; m_pDelayInfo->pBufferL->Skip(2, ret); m_pDelayInfo->pBufferR->Skip(2, ret); //try to flush the buffer TRACEA("try to flush the buffer again. ret=%d\n", ret); return Decode1Frame(mp3buf, 0, pcm_l, pcm_r, mp3data); //return 0; } //only skip the left bytes TRACEA("Skipped %d bytes at beginning\n", nLeft); m_pDelayInfo->nStartSkipped += nLeft; ret -= nLeft; //move the output data backward m_pDelayInfo->pBufferL->Skip(2, nLeft); m_pDelayInfo->pBufferR->Skip(2, nLeft); } int dataLenL = m_pDelayInfo->pBufferL->GetData((char*)pcm_l, 2); int dataLenR = m_pDelayInfo->pBufferR->GetData((char*)pcm_r, 2); assert(dataLenL == dataLenR); if(dataLenL <= 0) { //try to flush the buffer TRACEA("Skipped over, try to flush the buffer again. ret=%d\n", ret); return Decode1Frame(mp3buf, 0, pcm_l, pcm_r, mp3data); } ret = dataLenL; return ret; } }
void JobThreadFunc(void) { Lock(); O2KeyList keylist(RequestQueue); RequestQueue.clear(); Unlock(); if (keylist.size() == 0) return; O2NodeDB::NodeListT Nodes; // キーでループ O2KeyListIt it; for (it = keylist.begin(); it != keylist.end() && IsActive(); it++) { O2Key &key = *it; TRACEA("[GETDAT]"); TRACEW(it->url.c_str()); TRACEA("\n"); O2Node node; node.id = it->nodeid; node.ip = it->ip; node.port = it->port; // リクエスト発行 O2SocketSession ss; ss.ip = key.ip; ss.port = key.port; MakeRequest_Dat(&key.hash, NULL, &ss, Profile, DatIO, ss.sbuff); Client->AddRequest(&ss); ss.Wait(); HTTPHeader *header = (HTTPHeader*)ss.data; if (CheckResponse(&ss, header, NodeDB, node)) { // 本文のdat取り込み const char *rawdata = &ss.rbuff[header->length]; uint64 datsize = ss.rbuff.size() - header->length; ImportDat(DatIO, Profile, NULL, *header, rawdata, datsize, Logger, ss.ip, ss.port, QueryDB, hwndBaloonCallback, msgBaloonCallback); } if (header) delete header; Nodes.push_back(node); Sleep(IsActive() ? QUERY_DAT_INTERVAL_MS : 0); } O2NodeDB::NodeListT::iterator nit; for (nit = Nodes.begin(); nit != Nodes.end() && IsActive(); nit++) { if (nit->lastlink) { // 成功したノードをtouch NodeDB->touch(*nit); } else { // 失敗したノードをremove NodeDB->remove(*nit); KeyDB->DeleteKeyByNodeID(nit->id); } } }
DWORD WINAPI ChangeNotifyThread(NOTIFY_DATA *pnd) { HANDLE hChange; DWORD dwResult; TCHAR szDirectory[MAX_PATH]; //FILE_NOTIFY_INFORMATION notifyinfo; //HANDLE hDirectory; //OVERLAPPED overlapped = { 0 }; //hChange = CreateEvent(0, FALSE, FALSE, 0); //overlapped.hEvent = hChange; lstrcpy(szDirectory, pnd->szFile); // get the directory name from filename if(GetFileAttributes(szDirectory) != FILE_ATTRIBUTE_DIRECTORY) { TCHAR *slash = _tcsrchr(szDirectory, _T('\\')); if(slash) *slash = '\0'; } //hDirectory = CreateFile(szDirectory, FILE_LIST_DIRECTORY, FILE_SHARE_READ|FILE_SHARE_DELETE, // NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED , NULL); //ReadDirectoryChangesW(hDirectory, ¬ifyinfo, sizeof(notifyinfo), FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE, 0, &overlapped, 0); // watch the specified directory for changes hChange = FindFirstChangeNotification(szDirectory, FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE); do { HANDLE hEventList[2] = { hChange, pnd->hQuitEvent }; if((dwResult = WaitForMultipleObjects(1, hEventList, FALSE, INFINITE)) == WAIT_OBJECT_0) { NMFILECHANGE nmfc = { { pnd->hwndNotify, 0, FCN_FILECHANGE }, pnd->szFile }; FILETIME wt; ULONG64 n1, n2; //PostMessage(pnd->hwndNotify, WM_NOTIFY, 0, (LPARAM)pnd); GetLastWriteTime(pnd->szFile, &wt); //GetSystemTimeAsFileTime(&ft); n1 = (((ULONG64)wt.dwHighDateTime) << 32) + wt.dwLowDateTime; n2 = (((ULONG64)pnd->lastChange.dwHighDateTime) << 32) + pnd->lastChange.dwLowDateTime; TRACEA("%I64x %I64x (%d)\n", n1, n2, GetCurrentThreadId()); //if(*(ULONG64 *)&ft > *(ULONG64 *)&pnd->lastChange + (10000000 * 5)) if(n1 > n2 + (10000000 * 3)) { PostMessage(pnd->hwndNotify, WM_NOTIFY, 0, (LPARAM)&nmfc); } pnd->lastChange = wt; } FindNextChangeNotification(hChange); } while(dwResult == WAIT_OBJECT_0); // cleanup FindCloseChangeNotification(hChange); free(pnd); return 0; }
// // WM_MOUSEMOVE // // Handled captured mouse movement // LRESULT GridView::OnMouseMove(int x, int y) { ULONG lineNo, colIdx, portion; RECT rect; POINT pt = { x, y }; GVRow *gvrow = MouseToItem(x, y, &lineNo, &colIdx, &portion, 0); if(m_fMouseDown) { // // Mouse-scrolling: if the mouse is outside the client-area then we // need to scroll // GetActiveClientRect(&rect); // If mouse is within this area, we don't need to scroll if(PtInRect(&rect, pt)) { if(m_nScrollTimer != 0) { KillTimer(m_hWnd, m_nScrollTimer); m_nScrollTimer = 0; } } // If mouse is outside window, start a timer in // order to generate regular scrolling intervals else { if(m_nScrollTimer == 0) { m_nScrollCounter = 0; m_nScrollTimer = SetTimer(m_hWnd, 1, 30, 0); } } bool changed = false; if(m_nCurrentColumn != colIdx) { RefreshWindow(); m_nCurrentColumn = colIdx; changed = true; } if(m_nCurrentLine != lineNo) { RedrawLine(m_nCurrentLine); RedrawLine(lineNo); m_nCurrentLine = lineNo; changed = true; } if(changed) NotifyParent(GVN_SELCHANGED, gvrow); } else if(gvrow) { // GVRow *gvrow = MouseToItem(x, y, &lineNo, &colIdx, &portion, 0); // does the item under the mouse have a combobox button? if(gvrow->items[colIdx].state & (GVIS_DROPLIST|GVIS_DROPDOWN)) { // ok, is the mouse over the button itself? TRACEA("mouse over button\n"); } /* TOOLINFO ti = { sizeof(ti), 0, m_hWnd, 1 }; // support the tooltip GVRow *gvrow = MouseToItem(x, y, &lineNo, &colIdx, &portion, &ti.rect); char f[100]; wsprintf(f, "[%d,%d] %d %d %d %d\n", x, y, ti.rect.left, ti.rect.top, ti.rect.right, ti.rect.bottom); OutputDebugString(f); // SendMessage(m_hWndTooltip, TTM_DELTOOL, 0, (LPARAM)&ti); // SendMessage(m_hWndTooltip, TTM_ADDTOOL, 0, (LPARAM)&ti); ti.hwnd = m_hWnd; ti.uFlags = 0;//TTF_IDISHWND;//0; ti.uId = 1;//(ULONG)m_hWnd;//1; ti.hinst = 0; ti.lpszText = f; // SendMessage(m_hWndTooltip, TTM_ACTIVATE, TRUE, 0); SendMessage(m_hWndTooltip, TTM_NEWTOOLRECT, 0, (LPARAM)&ti); //RelayEvent(m_hWndTooltip, WM_MOUSEMOVE, x, y); SendMessage(m_hWndTooltip, TTM_SETTOOLINFO, 0, (LPARAM)&ti); TTHITTESTINFO hti = { m_hWnd, { x, y }, { sizeof(TOOLINFO) } }; if(SendMessage(m_hWndTooltip, TTM_HITTEST, 0, (LPARAM)&hti)) { OutputDebugString("smeg\n"); } else { OutputDebugString("head\n"); } //SendMessage(m_hWndTooltip, TTM_POPUP, 0, 0); */ } return 0; }