|
|
|
|
|
[原创]一段仿真PE加载器行为的程序
收藏一下! |
|
[求助]用 DELPHI 仿 DELPHI 中的一句语句!!
看了下,正常窗体风格: WS_BORDER WS_CAPTION WS_CLIPCHILDREN WS_CLIPSIBLINGS WS_DLGFRAME WS_GROUP WS_MAXIMIZEBOX WS_MINIMIZEBOX WS_SYSMENU WS_POPUPWINDOW WS_TABSTOP WS_THICKFRAME WS_VISIBLE MDIform的风格: WS_CHILD WS_CLIPCHILDREN WS_CLIPSIBLINGS WS_GROUP WS_MAXIMIZEBOX WS_MINIMIZEBOX WS_TABSTOP WS_VISIBLE |
|
|
|
[下载]XM音乐及播放器下载
收藏! |
|
[求助]用 DELPHI 仿 DELPHI 中的一句语句!!
SetWindowLong应该能做到,但窗口风格的常数就不知道了! |
|
谁对midiStream那几个api熟悉的?
/* native_midi: Hardware Midi support for the SDL_mixer library Copyright (C) 2000,2001 Florian 'Proff' Schulze This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Florian 'Proff' Schulze florian.proff.schulze@gmx.net $Id: native_midi_win32.c,v 1.3 2002/01/14 09:14:55 tksuoran Exp $ */ /* everything below is currently one very big bad hack ;) Proff */ #define WIN32_LEAN_AND_MEAN #include <stdlib.h> #include <limits.h> #include <windows.h> #include <windowsx.h> #include <mmsystem.h> #include <stdio.h> #include "arch/win32/native_midi.h" #define XCHG_SHORT(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF)) # define XCHG_LONG(x) ((((x)&0xFF)<<24) | \ (((x)&0xFF00)<<8) | \ (((x)&0xFF0000)>>8) | \ (((x)>>24)&0xFF)) #define LE_SHORT(x) x #define LE_LONG(x) x #define BE_SHORT(x) XCHG_SHORT(x) #define BE_LONG(x) XCHG_LONG(x) static UINT MidiDevice=MIDI_MAPPER; static HMIDISTRM hMidiStream; static NativeMidiSong *currentsong; static int getvl(NativeMidiSong *song) { int l=0; byte c; for (;;) { c=song->mididata.track[song->CurrentTrack].data[song->CurrentPos]; song->CurrentPos++; l += (c & 0x7f); if (!(c & 0x80)) return l; l<<=7; } } static void AddEvent(NativeMidiSong *song, DWORD at, DWORD type, byte event, byte a, byte b) { MIDIEVENT *CurEvent; if ((song->BytesRecorded[song->CurrentTrack]+(int)sizeof(MIDIEVENT))>=song->BufferSize[song->CurrentTrack]) { song->BufferSize[song->CurrentTrack]+=100*sizeof(MIDIEVENT); song->MidiEvents[song->CurrentTrack]=realloc(song->MidiEvents[song->CurrentTrack],song->BufferSize[song->CurrentTrack]); } CurEvent=(MIDIEVENT *)((byte *)song->MidiEvents[song->CurrentTrack]+song->BytesRecorded[song->CurrentTrack]); memset(CurEvent,0,sizeof(MIDIEVENT)); CurEvent->dwDeltaTime=at; CurEvent->dwEvent=event+(a<<8)+(b<<16)+(type<<24); song->BytesRecorded[song->CurrentTrack]+=3*sizeof(DWORD); } static void MidiTracktoStream(NativeMidiSong *song) { DWORD atime,len; byte event,type,a,b,c; byte laststatus,lastchan; song->CurrentPos=0; laststatus=0; lastchan=0; atime=0; for (;;) { if (song->CurrentPos>=song->mididata.track[song->CurrentTrack].len) return; atime+=getvl(song); event=song->mididata.track[song->CurrentTrack].data[song->CurrentPos]; song->CurrentPos++; if(event==0xF0 || event == 0xF7) // SysEx event { len=getvl(song); song->CurrentPos+=len; } else if(event==0xFF) // Meta event { type=song->mididata.track[song->CurrentTrack].data[song->CurrentPos]; song->CurrentPos++; len=getvl(song); switch(type) { case 0x2f: return; case 0x51: // Tempo a=song->mididata.track[song->CurrentTrack].data[song->CurrentPos]; song->CurrentPos++; b=song->mididata.track[song->CurrentTrack].data[song->CurrentPos]; song->CurrentPos++; c=song->mididata.track[song->CurrentTrack].data[song->CurrentPos]; song->CurrentPos++; AddEvent(song, atime, MEVT_TEMPO, c, b, a); break; default: song->CurrentPos+=len; break; } } else { a=event; if (a & 0x80) // status byte { lastchan=a & 0x0F; laststatus=(a>>4) & 0x07; a=song->mididata.track[song->CurrentTrack].data[song->CurrentPos]; song->CurrentPos++; a &= 0x7F; } switch(laststatus) { case 0: // Note off b=song->mididata.track[song->CurrentTrack].data[song->CurrentPos]; song->CurrentPos++; b &= 0x7F; AddEvent(song, atime, MEVT_SHORTMSG, (byte)((laststatus<<4)+lastchan+0x80), a, b); break; case 1: // Note on b=song->mididata.track[song->CurrentTrack].data[song->CurrentPos]; song->CurrentPos++; b &= 0x7F; AddEvent(song, atime, MEVT_SHORTMSG, (byte)((laststatus<<4)+lastchan+0x80), a, b); break; case 2: // Key Pressure b=song->mididata.track[song->CurrentTrack].data[song->CurrentPos]; song->CurrentPos++; b &= 0x7F; AddEvent(song, atime, MEVT_SHORTMSG, (byte)((laststatus<<4)+lastchan+0x80), a, b); break; case 3: // Control change b=song->mididata.track[song->CurrentTrack].data[song->CurrentPos]; song->CurrentPos++; b &= 0x7F; AddEvent(song, atime, MEVT_SHORTMSG, (byte)((laststatus<<4)+lastchan+0x80), a, b); break; case 4: // Program change a &= 0x7f; AddEvent(song, atime, MEVT_SHORTMSG, (byte)((laststatus<<4)+lastchan+0x80), a, 0); break; case 5: // Channel pressure a &= 0x7f; AddEvent(song, atime, MEVT_SHORTMSG, (byte)((laststatus<<4)+lastchan+0x80), a, 0); break; case 6: // Pitch wheel b=song->mididata.track[song->CurrentTrack].data[song->CurrentPos]; song->CurrentPos++; b &= 0x7F; AddEvent(song, atime, MEVT_SHORTMSG, (byte)((laststatus<<4)+lastchan+0x80), a, b); break; default: break; } } } } static int BlockOut(NativeMidiSong *song) { MMRESULT err; int BlockSize; if ((song->MusicLoaded) && (song->NewEvents)) { // proff 12/8/98: Added for savety midiOutUnprepareHeader((struct HMIDIOUT__ *)hMidiStream,&song->MidiStreamHdr,sizeof(MIDIHDR)); if (song->NewPos>=song->NewSize) return 0; BlockSize=(song->NewSize-song->NewPos); if (BlockSize<=0) return 0; if (BlockSize>36000) BlockSize=36000; song->MidiStreamHdr.lpData=(void *)((byte *)song->NewEvents+song->NewPos); song->NewPos+=BlockSize; song->MidiStreamHdr.dwBufferLength=BlockSize; song->MidiStreamHdr.dwBytesRecorded=BlockSize; song->MidiStreamHdr.dwFlags=0; // lprintf(LO_DEBUG,"Data: %p, Size: %i\n",MidiStreamHdr.lpData,BlockSize); err=midiOutPrepareHeader((struct HMIDIOUT__ *)hMidiStream,&song->MidiStreamHdr,sizeof(MIDIHDR)); if (err!=MMSYSERR_NOERROR) return 0; err=midiStreamOut(hMidiStream,&song->MidiStreamHdr,sizeof(MIDIHDR)); return 0; } return 1; } static void MIDItoStream(NativeMidiSong *song) { int BufferPos[MIDI_TRACKS]; MIDIEVENT *CurEvent; MIDIEVENT *NewEvent; int lTime; int Dummy; int Track; //if (!hMidiStream) //return; song->NewSize=0; for (song->CurrentTrack=0;song->CurrentTrack<MIDI_TRACKS;song->CurrentTrack++) { song->MidiEvents[song->CurrentTrack]=NULL; song->BytesRecorded[song->CurrentTrack]=0; song->BufferSize[song->CurrentTrack]=0; MidiTracktoStream(song); song->NewSize+=song->BytesRecorded[song->CurrentTrack]; BufferPos[song->CurrentTrack]=0; } song->NewEvents=realloc(song->NewEvents,song->NewSize); if (song->NewEvents) { song->NewPos=0; while (1) { lTime=INT_MAX; Track=-1; for (song->CurrentTrack=MIDI_TRACKS-1;song->CurrentTrack>=0;song->CurrentTrack--) { if ((song->BytesRecorded[song->CurrentTrack]>0) && (BufferPos[song->CurrentTrack]<song->BytesRecorded[song->CurrentTrack])) CurEvent=(MIDIEVENT *)((byte *)song->MidiEvents[song->CurrentTrack]+BufferPos[song->CurrentTrack]); else continue; if ((int)CurEvent->dwDeltaTime<=lTime) { lTime=CurEvent->dwDeltaTime; Track=song->CurrentTrack; } } if (Track==-1) break; else { CurEvent=(MIDIEVENT *)((byte *)song->MidiEvents[Track]+BufferPos[Track]); BufferPos[Track]+=12; NewEvent=(MIDIEVENT *)((byte *)song->NewEvents+song->NewPos); memcpy(NewEvent,CurEvent,12); song->NewPos+=12; } } song->NewPos=0; lTime=0; while (song->NewPos<song->NewSize) { NewEvent=(MIDIEVENT *)((byte *)song->NewEvents+song->NewPos); Dummy=NewEvent->dwDeltaTime; NewEvent->dwDeltaTime-=lTime; lTime=Dummy; if ((song->NewPos+12)>=song->NewSize) NewEvent->dwEvent |= MEVT_F_CALLBACK; song->NewPos+=12; } song->NewPos=0; song->MusicLoaded=1; //BlockOut(song); } for (song->CurrentTrack=0;song->CurrentTrack<MIDI_TRACKS;song->CurrentTrack++) { if (song->MidiEvents[song->CurrentTrack]) free(song->MidiEvents[song->CurrentTrack]); } } void CALLBACK MidiProc( HMIDIIN hMidi, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2 ) { switch( uMsg ) { case MOM_DONE: if ((currentsong->MusicLoaded) && ((DWORD)dwParam1 == (DWORD)¤tsong->MidiStreamHdr)) BlockOut(currentsong); break; case MOM_POSITIONCB: if ((currentsong->MusicLoaded) && ((DWORD)dwParam1 == (DWORD)¤tsong->MidiStreamHdr)) currentsong->MusicPlaying=0; break; default: break; } } int native_midi_init() { MMRESULT merr; HMIDISTRM MidiStream; merr=midiStreamOpen(&MidiStream,&MidiDevice,1,(DWORD)&MidiProc,0,CALLBACK_FUNCTION); if (merr!=MMSYSERR_NOERROR) MidiStream=0; midiStreamClose(MidiStream); if (!MidiStream) return 0; else return 1; } typedef struct { char ID[4]; int size; short format; short tracks; short deltatime; } fmidihdr; typedef struct { char ID[4]; int size; } fmiditrack; static void load_mididata(MIDI *mididata, FILE *fp) { fmidihdr midihdr; fmiditrack trackhdr; int i; if (!mididata) return; if (!fp) return; fread(&midihdr,1,14,fp); mididata->divisions=BE_SHORT(midihdr.deltatime); for (i=0;i<BE_SHORT(midihdr.tracks);i++) { fread(&trackhdr,1,8,fp); mididata->track[i].len=BE_LONG(trackhdr.size); mididata->track[i].data=malloc(mididata->track[i].len); if (mididata->track[i].data) fread(mididata->track[i].data,1,mididata->track[i].len,fp); } mididata->loaded=1; } NativeMidiSong *native_midi_loadsong(char *midifile) { FILE *fp; NativeMidiSong *newsong; newsong=malloc(sizeof(NativeMidiSong)); if (!newsong) return NULL; memset(newsong,0,sizeof(NativeMidiSong)); /* Open the file */ fp = fopen(midifile, "rb"); if ( fp != NULL ) { newsong->mididata.loaded=0; load_mididata(&newsong->mididata, fp); if (!newsong->mididata.loaded) { free(newsong); fclose(fp); return NULL; } fclose(fp); } else { free(newsong); return NULL; } MIDItoStream(newsong); return newsong; } void native_midi_freesong(NativeMidiSong *song) { if (hMidiStream) { midiStreamStop(hMidiStream); midiStreamClose(hMidiStream); } if (song) { if (song->NewEvents) free(song->NewEvents); free(song); } } void native_midi_start(NativeMidiSong *song) { MMRESULT merr; MIDIPROPTIMEDIV mptd; native_midi_stop(); if (!hMidiStream) { merr=midiStreamOpen(&hMidiStream,&MidiDevice,1,(DWORD)&MidiProc,0,CALLBACK_FUNCTION); if (merr!=MMSYSERR_NOERROR) { hMidiStream=0; return; } //midiStreamStop(hMidiStream); // MusicLoop=looping; currentsong=song; currentsong->NewPos=0; currentsong->MusicPlaying=1; mptd.cbStruct=sizeof(MIDIPROPTIMEDIV); mptd.dwTimeDiv=currentsong->mididata.divisions; merr=midiStreamProperty(hMidiStream,(LPBYTE)&mptd,MIDIPROP_SET | MIDIPROP_TIMEDIV); BlockOut(song); merr=midiStreamRestart(hMidiStream); } } void native_midi_stop() { if (!hMidiStream) return; midiStreamStop(hMidiStream); midiStreamClose(hMidiStream); currentsong=NULL; hMidiStream = 0; } int native_midi_active() { return currentsong->MusicPlaying; } void native_midi_setvolume(int volume) { } char *native_midi_error() { return ""; } |
|
谁对midiStream那几个api熟悉的?
Re: Looking for Visual Basic Source Code Posted by: moydog (IP Logged) Date: April 19, 2006 10:45PM Go here for the .frm [www.blackbeltvb.com] Option Explicit ' Midinote sample from BlackBeltVB.com ' [blackbeltvb.com] ' ' Written by Matt Hart ' Copyright 1999 by Matt Hart ' ' This software is FREEWARE. You may use it as you see fit for ' your own projects but you may not re-sell the original or the ' source code. Do not copy this sample to a collection, such as ' a CD-ROM archive. You may link directly to the original sample ' using "http://blackbeltvb.com/midinote.htm" ' ' No warranty express or implied, is given as to the use of this ' program. Use at your own risk. ' ' This one plays a few MIDI notes to the default MIDI ' device, showing you the basics of streaming MIDI output. ' ' It is a translation of a C program sent to me by ' Pier Calderan in the ' form of a question ... ' "How do I get this to work in VB?". Private Type midiHdr lpData As Long ' As String dwBufferLength As Long dwBytesRecorded As Long dwUser As Long dwFlags As Long lpNext As Long Reserved As Long dwOffset As Long dwReserved(0 To 3) As Long End Type Private Type MIDIPROPTIMEDIV cbStruct As Long dwTimeDiv As Long End Type Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (hpvDest As Any, hpvSource As Any, ByVal cbCopy As Long) Private Declare Function midiOutPrepareHeader Lib "winmm.dll" (ByVal hMidiOut As Long, lpMidiOutHdr As Any, ByVal uSize As Long) As Long Private Declare Function midiOutUnprepareHeader Lib "winmm.dll" (ByVal hMidiOut As Long, lpMidiOutHdr As Any, ByVal uSize As Long) As Long Private Declare Function midiStreamClose Lib "winmm.dll" (ByVal hms As Long) As Long Private Declare Function midiStreamOpen Lib "winmm.dll" (phms As Long, puDeviceID As Long, ByVal cMidi As Long, ByVal dwCallback As Long, ByVal dwInstance As Long, ByVal fdwOpen As Long) As Long Private Declare Function midiStreamOut Lib "winmm.dll" (ByVal hms As Long, pmh As Any, ByVal cbmh As Long) As Long Private Declare Function midiStreamProperty Lib "winmm.dll" (ByVal hms As Long, lppropdata As Any, ByVal dwProperty As Long) As Long Private Declare Function midiStreamRestart Lib "winmm.dll" (ByVal hms As Long) As Long Private Const GMEM_FIXED = &H0 Private Const GMEM_ZEROINIT = &H40 Private Const GPTR = (GMEM_FIXED Or GMEM_ZEROINIT) Private Declare Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Long, ByVal dwBytes As Long) As Long Private Declare Function GlobalFree Lib "kernel32" (ByVal hMem As Long) As Long Private Const MIDIMAPPER = (-1) Private Const MMSYSERR_NOERROR = 0 Private Const MIDIERR_BASE = 64 Private Const MIDIERR_STILLPLAYING = (MIDIERR_BASE + 1) ' still something playing Private Const CALLBACK_NULL = &H0 Private Const MEVT_F_SHORT = &H0& Private Const MIDIPROP_SET = &H80000000 Private Const MIDIPROP_TIMEDIV = &H1& Private Sub Command1_Click() Dim Phrase(0 To 18) As Long Phrase(2) = &H7F3C90 Phrase(3) = 32 Phrase(5) = &H7F3E90 Phrase(8) = &H7F4090 Phrase(9) = 48 Phrase(11) = &H3C90 Phrase(12) = 48 Phrase(14) = &H3E90 Phrase(15) = 48 Phrase(17) = &H4090 Dim lSize As Long, uDevice As Long lSize = (UBound(Phrase) - LBound(Phrase) + 1) * Len(Phrase(0)) uDevice = MIDIMAPPER Dim Handle As Long, mHdr As midiHdr, hMem As Long, prop As MIDIPROPTIMEDIV If midiStreamOpen(Handle, uDevice, 1, 0, 0, CALLBACK_NULL) = MMSYSERR_NOERROR Then prop.cbStruct = Len(prop) prop.dwTimeDiv = Val(Text1.Text) midiStreamProperty Handle, prop, MIDIPROP_SET Or MIDIPROP_TIMEDIV hMem = GlobalAlloc(GPTR, lSize) CopyMemory ByVal hMem, Phrase(0), lSize mHdr.lpData = hMem ' or VarPtr(Phrase(0)) without the global memory junk, but Phrase(0) might moved by VB unexpectedly mHdr.dwBufferLength = lSize mHdr.dwBytesRecorded = lSize - 4 If midiOutPrepareHeader(Handle, mHdr, Len(mHdr)) = MMSYSERR_NOERROR Then midiStreamOut Handle, mHdr, Len(mHdr) End If midiStreamRestart Handle Do While midiOutUnprepareHeader(Handle, mHdr, Len(mHdr)) = MIDIERR_STILLPLAYING: DoEvents: Loop midiStreamClose Handle GlobalFree hMem End If End Sub Private Sub Form_Load() Command1_Click End Sub |
|
谁对midiStream那几个api熟悉的?
midiConnect 将指定的MIDI输入设备连接到输出设备 midiDisconnect 断开MIDI输入设备和输出设备的连接 midiInAddBuffer 向指定的音乐仪器数字接口的输入设备增加 一个缓冲区 midiInClose 关闭指定的音乐仪器数字接口的输入设备 midiInGetDveCaps 查询指定的音乐仪器数字接口的输入设备, 以确定其性能 midiInGetErrorText 检取有关音乐仪器数字接口的输入设备指定 错误的文本说明 midiInGetID 获得一个音乐一起数字接口的输入设备的标 识符 midiInGetNumDevs 检取系统中音乐仪器数字接口的输入设备的 数量 midiInMessage 向指定的音乐仪器数字接口的输入设备驱动 器发送一条消息 midiInOpen 打开指定的音乐仪器数字接口的输入设备 midiInPrepareHeader 为音乐仪器数字接口的输入设备准备一个缓 冲区 midiInReset 在给定的MIDI输入设备上输入,并将所有挂 起的输入缓冲区标记为已执行的 midiInStart 启动在指定的音乐仪器数字接口的输入设备 上的输入 midiInStop 停止在给定的音乐仪器数字接口的输入设备 上的输入 midiInUnprepareHeader 消除由midiInPrepareHeader函数完成的准备 midiOutCacheDrumPatches 请求内部的一个MIDI合成设备预装指定的基于 键的击打音色集 midiOutCachePatches 请求内部的音乐仪器数字接口的合成设备预装 指定的音色集 midiOutClose 关闭指定的音乐仪器数字接口的输出设备 midiOutGetDevCaps 查询指定的音乐仪器数字接口的输出设备,以 确定其性能 midiOutGetErrorText 检取有关MIDI输出设备指定采取的文本说明 midiOutGetID 检取指定的MIDI输出设备的标识符 midiOutGetNumDevs 检取系统中存在的MIDI输出设备的数量 midiOutGetVolume 返回一个MIDI输出设备的当前卷设置 midiOutLongMsg 向指定的MIDI输出设备发送一条系统专用的 MIDI消息 midiOutMessage 向一MIDI输出设备驱动器发送一条消息 midiOutOpen 打开指定的MIDI输出设备进行回放 midiOutPrepareHeader 为MIDI输出设备准备一个缓冲区 midiOutReset 为指定的MIDI输出设备关闭所有MIDI通道上的 所有标志 midiOutSetVolume 设置一个MIDI输出设备的卷 midiOutShortMsg 向指定的MIDI输出设备发送一条短MIDI消息 midiOutUnprepareHeader 清除由midiOutPrepareHeader函数完成的准备 midiStreamClose 关闭一个打开的MIDI流 midiStreamOpen 为输出,打开一个MIDI流 midiStreamOut 在MIDI输出设备上播放或排队一个MIDI数据流 midiStreamPause 暂停一个MIDI流的播放 midiStreamPosition 在一个MIDI流中检取当前位置 midiStreamProperty 设置或检取与MIDI输出设备相关MIDI数据流的 特性 midiStreamRestart 重新启动一个暂停的MIDI流 midiStreamStop 关掉指定MIDI输出设备的所有MIDI通道 只有这些解释,但没具体用过! |
|
|
|
|
|
|
|
|
|
|
|
VB6.0调用 VC++ dll 问题
COM组件吧,引用试一下! |
|
[求助]dll嵌入exe,exe退出时dll不能退出的问题
来个转贴[ZT] 除虫记之八(WM_QUIT和结束线程:1小时/1人) 公测的时候又发现一个问题,因为一个商务上问题,程序中去掉了一个模块(dll)的调用,打包公测后,发现程序在退出后而聊天进程没有退出,等待了很长时间也没有退出。 开发人员在调试的时候,已经在debug版本下重现了这个bug,跟踪代码出错部分的流程如下: 发送WM_QUIT消息给一个工作线程让其退出; 用WaitForSingleObject等待那个线程的句柄有信号; 如果有信号,就直接CloseHandle掉这个线程句柄; 如果超时没有信号,就直接用_endthreadex()杀死线程。 开发人员跟踪了好多次发现消息发送过去后线程并没有退出,每次都要超时进入强杀流程,但强杀调用确没有杀死线程,从thread里面还可以明确的看到这个线程在运行,于是就导致了进程没有退出! 跟踪了好几次都找不到问题所在,让我过去看看。 很明显,进程没有退出,就是因为这个线程没有退出的缘故。我一开始怀疑是不是线程没有收到这个消息,于是在处理消息的地方加上断点,ft,结果频频进入断点,程序一下子就失去了反应,连VC都没有响应了,不得已在进程管理器中杀死,按说在调试状态,进程管理器是不让杀的,但不知为何偏偏杀死了,且不管他。把断点去掉,在Post线程消息前加断点,然后再在线程的消息处理中加断点。运行,Post线程消息成功,F5运行,靠,竟然没有走到线程消息处理的断点里面。线程没有收到消息???? 运行多次,都是同一个现象。 因为只是一个杀死线程的操作,想让线程死还不容易啊,于是建议开发人员用TerminateThread()强杀线程,开发人员开始不理解,说线程是用_beginthreadex启动的,应该用_endthreadex杀死。我说就按我说的做,呵呵,线程如期被我们干掉了,进程退出了。 趁此机会,又给开发人员讲解了一番C运行库函数和Win32API的优劣比较。 让他们编译release版后送给测试部去验证,我又开始仔细那个线程处理消息的流程,我打了好多调试语句,怎么都发现没有收到退出的消息。晕啊。 忽然,注意到了WM_QUIT消息,哈,想起来了,自己曾经又一次就是用这个消息让线程退出,但没有成功,后来改程自定义的消息就可以了,立刻动手改成WM_USER+113,哈,收到了退出的消息,线程如期自动退出了! 哈哈,立刻又第n次的简单看了看WM_QUIT消息,然后告诉开发人员说WM_QUIT消息只能由应用程序主线程处理做程序退出。 我犯了一个大错误! 刚转了一圈回来,开发人员小声的说不是WM_QUIT消息的问题,被我听到了。 立刻追问,原来开发人员第一次的认真看了看WM_QUIT消息的MSDN文档,发现并不是线程不能处理WM_QUIT消息,而是线程中用GetMessage接收消息,而接收到这个消息后GetMessage返回0,就是这个0,被程序用if给if掉了! 我犯了一个大错误!我以为我对API已经很熟悉了,但看来远远不是!远远不是! 教训:尽可能用Win32的API,尽量的少用 c 运行库函数。WM_QUIT消息可以被任何线程处理。 |
操作理由
RANk
{{ user_info.golds == '' ? 0 : user_info.golds }}
雪币
{{ experience }}
课程经验
{{ score }}
学习收益
{{study_duration_fmt}}
学习时长
基本信息
荣誉称号:
{{ honorary_title }}
能力排名:
No.{{ rank_num }}
等 级:
LV{{ rank_lv-100 }}
活跃值:
在线值:
浏览人数:{{ visits }}
最近活跃:{{ last_active_time }}
注册时间:{{ user_info.create_date_jsonfmt }}
勋章
兑换勋章
证书
证书查询 >
能力值